コード例 #1
0
ファイル: xautolock_diy.c プロジェクト: Fat-Zer/tdebase
/*
 *  Function for initialising the whole shebang.
 */
void
xautolock_initDiy (Display* d)
{
  int s;

  queue.display = d;
  queue.tail = 0;
  queue.head = 0; 

  for (s = -1; ++s < ScreenCount (d); )
  {
    Window root = RootWindowOfScreen (ScreenOfDisplay (d, s));
    addToQueue (root);
#if 0
    selectEvents (root, True);
#endif
  }
}
コード例 #2
0
ファイル: xautolock_diy.c プロジェクト: Fat-Zer/tdebase
static void
processQueue (time_t age)
{
  if (queue.head)
  {
    time_t now = time (0);
    xautolock_item current = queue.head;

    while (current && current->creationtime + age < now)
    {
      selectEvents (current->window, False);
      queue.head = current->next;
      free (current);
      current = queue.head;
    }

    if (!queue.head) queue.tail = 0;
  }
}
コード例 #3
0
void
CXWindowsPrimaryScreen::createWindow()
{
	assert(m_window == None);

	// get size of screen
	SInt32 x, y, w, h;
	m_screen->getShape(x, y, w, h);

	// grab window attributes.  this window is used to capture user
	// input when the user is focused on another client.  don't let
	// the window manager mess with it.
	XSetWindowAttributes attr;
	attr.event_mask            = PointerMotionMask |
								 ButtonPressMask | ButtonReleaseMask |
								 KeyPressMask | KeyReleaseMask |
								 KeymapStateMask | PropertyChangeMask;
	attr.do_not_propagate_mask = 0;
	attr.override_redirect     = True;
	attr.cursor                = m_screen->getBlankCursor();

	{
		// create the grab window
		CDisplayLock display(m_screen);
		m_window = XCreateWindow(display, m_screen->getRoot(),
								x, y, w, h, 0, 0,
								InputOnly, CopyFromParent,
								CWDontPropagate | CWEventMask |
								CWOverrideRedirect | CWCursor,
								&attr);
		if (m_window == None) {
			throw XScreenOpenFailure();
		}
		LOG((CLOG_DEBUG "window is 0x%08x", m_window));

		// start watching for events on other windows
		selectEvents(display, m_screen->getRoot());
	}

	// tell generic screen about the window
	m_screen->setWindow(m_window);
}
コード例 #4
0
bool
CXWindowsPrimaryScreen::onEvent(CEvent* event)
{
	assert(event != NULL);
	XEvent& xevent = event->m_event;

	// let input methods try to handle event first
	if (m_ic != NULL) {
		// XFilterEvent() may eat the event and generate a new KeyPress
		// event with a keycode of 0 because there isn't an actual key
		// associated with the keysym.  but the KeyRelease may pass
		// through XFilterEvent() and keep its keycode.  this means
		// there's a mismatch between KeyPress and KeyRelease keycodes.
		// since we use the keycode on the client to detect when a key
		// is released this won't do.  so we remember the keycode on
		// the most recent KeyPress (and clear it on a matching
		// KeyRelease) so we have a keycode for a synthesized KeyPress.
		if (xevent.type == KeyPress && xevent.xkey.keycode != 0) {
			m_lastKeycode = xevent.xkey.keycode;
		}
		else if (xevent.type == KeyRelease &&
			xevent.xkey.keycode == m_lastKeycode) {
			m_lastKeycode = 0;
		}

		// now filter the event
		if (XFilterEvent(&xevent, None)) {
			return true;
		}
	}

	// handle event
	switch (xevent.type) {
	case CreateNotify:
		{
			// select events on new window
			CDisplayLock display(m_screen);
			selectEvents(display, xevent.xcreatewindow.window);
		}
		return true;

	case MappingNotify:
		// keyboard mapping changed
		updateKeys();
		return true;

	case KeyPress:
		{
			LOG((CLOG_DEBUG1 "event: KeyPress code=%d, state=0x%04x", xevent.xkey.keycode, xevent.xkey.state));
			const KeyModifierMask mask = mapModifier(xevent.xkey.state);
			KeyID key                  = mapKey(&xevent.xkey);
			if (key != kKeyNone) {
				// check for ctrl+alt+del emulation
				if ((key == kKeyPause || key == kKeyBreak) &&
					(mask & (KeyModifierControl | KeyModifierAlt)) ==
							(KeyModifierControl | KeyModifierAlt)) {
					// pretend it's ctrl+alt+del
					LOG((CLOG_DEBUG "emulate ctrl+alt+del"));
					key = kKeyDelete;
				}

				// get which button.  see call to XFilterEvent() above
				// for more info.
				KeyCode keycode = xevent.xkey.keycode;
				if (keycode == 0) {
					keycode = m_lastKeycode;
				}

				// handle key
				m_receiver->onKeyDown(key, mask,
								static_cast<KeyButton>(keycode));
				if (key == kKeyCapsLock && m_capsLockHalfDuplex) {
					m_receiver->onKeyUp(key, mask | KeyModifierCapsLock,
								static_cast<KeyButton>(keycode));
				}
				else if (key == kKeyNumLock && m_numLockHalfDuplex) {
					m_receiver->onKeyUp(key, mask | KeyModifierNumLock,
								static_cast<KeyButton>(keycode));
				}
			}
		}
		return true;

	case KeyRelease:
		{
			const KeyModifierMask mask = mapModifier(xevent.xkey.state);
			KeyID key                  = mapKey(&xevent.xkey);
			if (key != kKeyNone) {
				// check if this is a key repeat by getting the next
				// KeyPress event that has the same key and time as
				// this release event, if any.  first prepare the
				// filter info.
				CKeyEventInfo filter;
				filter.m_event   = KeyPress;
				filter.m_window  = xevent.xkey.window;
				filter.m_time    = xevent.xkey.time;
				filter.m_keycode = xevent.xkey.keycode;

				// now check for event
				bool hasPress;
				{
					XEvent xevent2;
					CDisplayLock display(m_screen);
					hasPress = (XCheckIfEvent(display, &xevent2,
									&CXWindowsPrimaryScreen::findKeyEvent,
									(XPointer)&filter) == True);
				}

				// check for ctrl+alt+del emulation
				if ((key == kKeyPause || key == kKeyBreak) &&
					(mask & (KeyModifierControl | KeyModifierAlt)) ==
							(KeyModifierControl | KeyModifierAlt)) {
					// pretend it's ctrl+alt+del and ignore autorepeat
					LOG((CLOG_DEBUG "emulate ctrl+alt+del"));
					key      = kKeyDelete;
					hasPress = false;
				}


				if (!hasPress) {
					// no press event follows so it's a plain release
					LOG((CLOG_DEBUG1 "event: KeyRelease code=%d, state=0x%04x", xevent.xkey.keycode, xevent.xkey.state));
					if (key == kKeyCapsLock && m_capsLockHalfDuplex) {
						m_receiver->onKeyDown(key, mask,
								static_cast<KeyButton>(xevent.xkey.keycode));
					}
					else if (key == kKeyNumLock && m_numLockHalfDuplex) {
						m_receiver->onKeyDown(key, mask,
								static_cast<KeyButton>(xevent.xkey.keycode));
					}
					m_receiver->onKeyUp(key, mask,
								static_cast<KeyButton>(xevent.xkey.keycode));
				}
				else {
					// found a press event following so it's a repeat.
					// we could attempt to count the already queued
					// repeats but we'll just send a repeat of 1.
					// note that we discard the press event.
					LOG((CLOG_DEBUG1 "event: repeat code=%d, state=0x%04x", xevent.xkey.keycode, xevent.xkey.state));
					m_receiver->onKeyRepeat(key, mask, 1,
								static_cast<KeyButton>(xevent.xkey.keycode));
				}
			}
		}
		return true;

	case ButtonPress:
		{
			LOG((CLOG_DEBUG1 "event: ButtonPress button=%d", xevent.xbutton.button));
			const ButtonID button = mapButton(xevent.xbutton.button);
			if (button != kButtonNone) {
				m_receiver->onMouseDown(button);
			}
		}
		return true;

	case ButtonRelease:
		{
			LOG((CLOG_DEBUG1 "event: ButtonRelease button=%d", xevent.xbutton.button));
			const ButtonID button = mapButton(xevent.xbutton.button);
			if (button != kButtonNone) {
				m_receiver->onMouseUp(button);
			}
			else if (xevent.xbutton.button == 4) {
				// wheel forward (away from user)
				m_receiver->onMouseWheel(120);
			}
			else if (xevent.xbutton.button == 5) {
				// wheel backward (toward user)
				m_receiver->onMouseWheel(-120);
			}
		}
		return true;

	case MotionNotify:
		{
			LOG((CLOG_DEBUG2 "event: MotionNotify %d,%d", xevent.xmotion.x_root, xevent.xmotion.y_root));

			// compute motion delta (relative to the last known
			// mouse position)
			SInt32 x = xevent.xmotion.x_root - m_x;
			SInt32 y = xevent.xmotion.y_root - m_y;

			// save position to compute delta of next motion
			m_x = xevent.xmotion.x_root;
			m_y = xevent.xmotion.y_root;

			if (xevent.xmotion.send_event) {
				// we warped the mouse.  discard events until we
				// find the matching sent event.  see
				// warpCursorNoFlush() for where the events are
				// sent.  we discard the matching sent event and
				// can be sure we've skipped the warp event.
				CDisplayLock display(m_screen);
				do {
					XMaskEvent(display, PointerMotionMask, &xevent);
				} while (!xevent.xmotion.send_event);
			}
			else if (!isActive()) {
				// motion on primary screen
				m_receiver->onMouseMovePrimary(m_x, m_y);
			}
			else {
				// motion on secondary screen.  warp mouse back to
				// center.
				//
				// my lombard (powerbook g3) running linux and
				// using the adbmouse driver has two problems:
				// first, the driver only sends motions of +/-2
				// pixels and, second, it seems to discard some
				// physical input after a warp.  the former isn't a
				// big deal (we're just limited to every other
				// pixel) but the latter is a PITA.  to work around
				// it we only warp when the mouse has moved more
				// than s_size pixels from the center.
				static const SInt32 s_size = 32;
				if (xevent.xmotion.x_root - m_xCenter < -s_size ||
					xevent.xmotion.x_root - m_xCenter >  s_size ||
					xevent.xmotion.y_root - m_yCenter < -s_size ||
					xevent.xmotion.y_root - m_yCenter >  s_size) {
					CDisplayLock display(m_screen);
					warpCursorNoFlush(display, m_xCenter, m_yCenter);
				}

				// send event if mouse moved.  do this after warping
				// back to center in case the motion takes us onto
				// the primary screen.  if we sent the event first
				// in that case then the warp would happen after
				// warping to the primary screen's enter position,
				// effectively overriding it.
				if (x != 0 || y != 0) {
					m_receiver->onMouseMoveSecondary(x, y);
				}
			}
		}
		return true;
	}

	return false;
}
コード例 #5
0
ファイル: xautolock_diy.c プロジェクト: Fat-Zer/tdebase
/*
 *  Function for selecting all interesting events on a given 
 *  (tree of) window(s).
 */
static void 
selectEvents (Window window, Bool substructureOnly)
{
  Window            root;              /* root window of the window */
  Window            parent;            /* parent of the window      */
  Window*           children;          /* children of the window    */
  unsigned          nofChildren = 0;   /* number of children        */
  unsigned          i;                 /* loop counter              */
  XWindowAttributes attribs;           /* attributes of the window  */

  if( xautolock_ignoreWindow( window ))
      return;
 /*
  *  Start by querying the server about the root and parent windows.
  */
  if (!XQueryTree (queue.display, window, &root, &parent,
                   &children, &nofChildren))
  {
    return;
  }

  if (nofChildren) (void) XFree ((char*) children);

 /*
  *  Build the appropriate event mask. The basic idea is that we don't
  *  want to interfere with the normal event propagation mechanism if
  *  we don't have to.
  *
  *  On the root window, we need to ask for both substructureNotify 
  *  and KeyPress events. On all other windows, we always need 
  *  substructureNotify, but only need Keypress if some other client
  *  also asked for them, or if they are not being propagated up the
  *  window tree.
  */
#if 0
  if (substructureOnly)
  {
    (void) XSelectInput (queue.display, window, SubstructureNotifyMask);
  }
  else
  {
    if (parent == None) /* the *real* rootwindow */
    {
      attribs.all_event_masks = 
      attribs.do_not_propagate_mask = KeyPressMask;
    }
    else if (!XGetWindowAttributes (queue.display, window, &attribs))
#else
    {
    if (!XGetWindowAttributes (queue.display, window, &attribs))
#endif
    {
      return;
    }

#if 0
    (void) XSelectInput (queue.display, window, 
                           SubstructureNotifyMask
                         | (  (  attribs.all_event_masks
                               | attribs.do_not_propagate_mask)
                            & KeyPressMask));
#else
    {
    int mask = SubstructureNotifyMask | attribs.your_event_mask;
    if( !substructureOnly )
        {
        mask |=            (  (  attribs.all_event_masks
                               | attribs.do_not_propagate_mask)
                            & KeyPressMask  );
        }
    (void) XSelectInput (queue.display, window, mask );
    }
#endif

  }

 /*
  *  Now ask for the list of children again, since it might have changed
  *  in between the last time and us selecting SubstructureNotifyMask.
  *
  *  There is a (very small) chance that we might process a subtree twice:
  *  child windows that have been created after our XSelectinput() has
  *  been processed but before we get to the XQueryTree() bit will be 
  *  in this situation. This is harmless. It could be avoided by using
  *  XGrabServer(), but that'd be an impolite thing to do, and since it
  *  isn't required...
  */
  if (!XQueryTree (queue.display, window, &root, &parent,
                   &children, &nofChildren))
  {
    return;
  }

 /*
  *  Now do the same thing for all children.
  */
  for (i = 0; i < nofChildren; ++i)
  {
    selectEvents (children[i], substructureOnly);
  }

  if (nofChildren) (void) XFree ((char*) children);
}

#if 0
/*
 *  Function for processing any events that have come in since 
 *  last time. It is crucial that this function does not block
 *  in case nothing interesting happened.
 */
void
processEvents (void)
{
  while (XPending (queue.display))
  {
    XEvent event;

    if (XCheckMaskEvent (queue.display, SubstructureNotifyMask, &event))
    {
      if (event.type == CreateNotify)
      {
        addToQueue (event.xcreatewindow.window);
      }
    }
    else
    {
      (void) XNextEvent (queue.display, &event);
    }

   /*
    *  Reset the triggers if and only if the event is a
    *  KeyPress event *and* was not generated by XSendEvent().
    */
    if (   event.type == KeyPress
        && !event.xany.send_event)
    {
      resetTriggers ();
    }
  }

 /*
  *  Check the window queue for entries that are older than
  *  CREATION_DELAY seconds.
  */
  processQueue ((time_t) CREATION_DELAY);
}
#else
void xautolock_processEvent( XEvent* event )
{
      if (event->type == CreateNotify)
      {
        addToQueue (event->xcreatewindow.window);
      }
   /*
    *  Reset the triggers if and only if the event is a
    *  KeyPress event *and* was not generated by XSendEvent().
    */
    if (   event->type == KeyPress
        && !event->xany.send_event)
    {
      xautolock_resetTriggers ();
    }
}

void xautolock_processQueue()
{
 /*
  *  Check the window queue for entries that are older than
  *  CREATION_DELAY seconds.
  */
  processQueue ((time_t) CREATION_DELAY);
}