moved some code around (regarding event handling) in preparation for upcoming features

This commit is contained in:
markt 2007-03-04 17:47:37 +00:00
parent 9477af82a5
commit 4c1a242968
9 changed files with 110 additions and 158 deletions

View file

@ -54,11 +54,11 @@ public:
virtual void exposeEvent(XExposeEvent &) { }
virtual void motionNotifyEvent(XMotionEvent &) { }
virtual void keyPressEvent(XKeyEvent &) { }
#ifdef NOT_USED
virtual void keyReleaseEvent(XKeyEvent &) { }
#endif
virtual void leaveNotifyEvent(XCrossingEvent &) { }
virtual void enterNotifyEvent(XCrossingEvent &) { }
virtual void notifyUngrabKeyboard() { }
};
} // end namespace FbTk

View file

@ -66,6 +66,26 @@ EventHandler *EventManager::find(Window win) {
return m_eventhandlers[win];
}
bool EventManager::grabKeyboard(EventHandler &ev, Window win) {
if (m_grabbing_keyboard)
ungrabKeyboard();
int ret = XGrabKeyboard(App::instance()->display(), win, False,
GrabModeAsync, GrabModeAsync, CurrentTime);
if (ret == Success) {
m_grabbing_keyboard = &ev;
return true;
}
return false;
}
void EventManager::ungrabKeyboard() {
XUngrabKeyboard(App::instance()->display(), CurrentTime);
if (m_grabbing_keyboard)
m_grabbing_keyboard->notifyUngrabKeyboard();
m_grabbing_keyboard = 0;
}
Window EventManager::getEventWindow(XEvent &ev) {
// we only have cases for events that differ from xany
@ -156,9 +176,7 @@ void EventManager::dispatch(Window win, XEvent &ev, bool parent) {
evhand->keyPressEvent(ev.xkey);
break;
case KeyRelease:
#ifdef NOT_USED
evhand->keyReleaseEvent(ev.xkey);
#endif
break;
case ButtonPress:
evhand->buttonPressEvent(ev.xbutton);

View file

@ -43,6 +43,10 @@ public:
void add(EventHandler &ev, Window win) { registerEventHandler(ev, win); }
void remove(Window win) { unregisterEventHandler(win); }
bool grabKeyboard(EventHandler &ev, Window win);
void ungrabKeyboard();
EventHandler *grabbingKeyboard() { return m_grabbing_keyboard; }
EventHandler *find(Window win);
// Some events have the parent window as the xany.window
@ -53,13 +57,14 @@ public:
void unregisterEventHandler(Window win);
private:
EventManager() { }
EventManager(): m_grabbing_keyboard(0) { }
~EventManager();
void dispatch(Window win, XEvent &event, bool parent = false);
typedef std::map<Window, EventHandler *> EventHandlerMap;
EventHandlerMap m_eventhandlers;
EventHandlerMap m_parent;
EventHandler *m_grabbing_keyboard;
};
} //end namespace FbTk

View file

@ -30,6 +30,8 @@
#include "fluxbox.hh"
#include "FbWinFrameTheme.hh"
#include "FbTk/EventManager.hh"
#include <string>
#include <iostream>
@ -82,7 +84,7 @@ bool doSkipWindow(const WinClient &winclient, int opts) {
void FocusControl::cycleFocus(FocusedWindows *window_list, int opts, bool cycle_reverse) {
if (!m_cycling_list) {
if (&m_screen == Fluxbox::instance()->watchingScreen())
if (&m_screen == FbTk::EventManager::instance()->grabbingKeyboard())
// only set this when we're waiting for modifiers
m_cycling_list = window_list;
m_was_iconic = 0;

View file

@ -28,6 +28,7 @@
#include "Screen.hh"
#include "fluxbox.hh"
#include "Keys.hh"
#include "Window.hh"
#include "Workspace.hh"
#include "Netizen.hh"
@ -364,6 +365,7 @@ BScreen::BScreen(FbTk::ResourceManager &rm,
m_altname(altscreenname),
m_focus_control(new FocusControl(*this)),
m_placement_strategy(new ScreenPlacement(*this)),
m_cycling(false),
m_xinerama_headinfo(0),
m_restart(false),
m_shutdown(false) {
@ -416,7 +418,8 @@ BScreen::BScreen(FbTk::ResourceManager &rm,
screenNumber(), XVisualIDFromVisual(rootWindow().visual()),
rootWindow().depth());
FbTk::EventManager *evm = FbTk::EventManager::instance();
evm->add(*this, rootWindow());
rootWindow().setCursor(XCreateFontCursor(disp, XC_left_ptr));
// load this screens resources
@ -538,6 +541,9 @@ BScreen::~BScreen() {
if (! managed)
return;
FbTk::EventManager *evm = FbTk::EventManager::instance();
evm->remove(rootWindow());
if (m_rootmenu.get() != 0)
m_rootmenu->removeAll();
@ -780,6 +786,59 @@ void BScreen::update(FbTk::Subject *subj) {
}
void BScreen::keyPressEvent(XKeyEvent &ke) {
Fluxbox::instance()->keys()->doAction(ke.type, ke.state, ke.keycode);
}
void BScreen::keyReleaseEvent(XKeyEvent &ke) {
if (!m_cycling)
return;
unsigned int state = FbTk::KeyUtil::instance().cleanMods(ke.state);
state &= ~FbTk::KeyUtil::instance().keycodeToModmask(ke.keycode);
if (!state) // all modifiers were released
FbTk::EventManager::instance()->ungrabKeyboard();
}
void BScreen::buttonPressEvent(XButtonEvent &be) {
if (be.button == 1 && !isRootColormapInstalled())
imageControl().installRootColormap();
Keys *keys = Fluxbox::instance()->keys();
keys->doAction(be.type, be.state, be.button);
}
void BScreen::notifyUngrabKeyboard() {
m_cycling = false;
focusControl().stopCyclingFocus();
}
void BScreen::cycleFocus(int options, bool reverse) {
// get modifiers from event that causes this for focus order cycling
XEvent ev = Fluxbox::instance()->lastEvent();
unsigned int mods = 0;
if (ev.type == KeyPress)
mods = FbTk::KeyUtil::instance().cleanMods(ev.xkey.state);
else if (ev.type == ButtonPress)
mods = FbTk::KeyUtil::instance().cleanMods(ev.xbutton.state);
if (!m_cycling && mods) {
m_cycling = true;
FbTk::EventManager::instance()->grabKeyboard(*this, rootWindow().window());
}
if (mods == 0) // can't stacked cycle unless there is a mod to grab
options |= FocusControl::CYCLELINEAR;
FocusControl::FocusedWindows *win_list =
(options & FocusControl::CYCLELINEAR) ?
&focusControl().creationOrderList() :
&focusControl().focusedOrderList();
focusControl().cycleFocus(win_list, options, reverse);
}
FbTk::Menu *BScreen::createMenu(const string &label) {
FbTk::Menu *menu = new FbMenu(menuTheme(),
imageControl(),
@ -2054,16 +2113,6 @@ void BScreen::renderPosWindow() {
}
/**
Called when a set of watched modifiers has been released
*/
void BScreen::notifyReleasedKeys() {
focusControl().stopCyclingFocus();
}
void BScreen::updateSize() {
// force update geometry
rootWindow().updateGeometry();

View file

@ -32,6 +32,8 @@
#include "MenuTheme.hh"
#include "PlacementStrategy.hh"
#include "FbTk/EventHandler.hh"
#include "FbTk/TypeAhead.hh"
#include "FbTk/Resource.hh"
#include "FbTk/Subject.hh"
#include "FbTk/MultLayers.hh"
@ -78,7 +80,8 @@ class Subject;
/**
Create workspaces, handles switching between workspaces and windows
*/
class BScreen : public FbTk::Observer, private FbTk::NotCopyable {
class BScreen: public FbTk::EventHandler, public FbTk::Observer,
private FbTk::NotCopyable {
public:
/// a window becomes active / focussed on a different workspace
enum FollowModel {
@ -209,6 +212,13 @@ public:
void update(FbTk::Subject *subj);
void keyPressEvent(XKeyEvent &ke);
void keyReleaseEvent(XKeyEvent &ke);
void buttonPressEvent(XButtonEvent &be);
void notifyUngrabKeyboard();
void cycleFocus(int opts, bool reverse);
FbTk::Menu *createMenu(const std::string &label);
FbTk::Menu *createToggleMenu(const std::string &label);
void hideMenus();
@ -294,8 +304,6 @@ public:
void showGeometry(int width, int height);
void hideGeometry();
void notifyReleasedKeys();
void setLayer(FbTk::XLayerItem &item, int layernum);
// remove? no, items are never removed from their layer until they die
@ -477,6 +485,8 @@ private:
typedef std::map<Window, WinClient *> Groupables;
Groupables m_expecting_groups;
bool m_cycling;
// Xinerama related private data
bool m_xinerama_avail;
int m_xinerama_num_heads;

View file

@ -42,59 +42,15 @@
#include <functional>
void NextWindowCmd::execute() {
Fluxbox *fb = Fluxbox::instance();
BScreen *screen = fb->keyScreen();
if (screen != 0) {
// get modifiers from event that causes this for focus order cycling
unsigned int mods = 0;
XEvent ev = fb->lastEvent();
if (ev.type == KeyPress) {
mods = FbTk::KeyUtil::instance().cleanMods(ev.xkey.state);
} else if (ev.type == ButtonPress) {
mods = FbTk::KeyUtil::instance().cleanMods(ev.xbutton.state);
}
int options = m_option;
if (mods == 0) // can't stacked cycle unless there is a mod to grab
options |= FocusControl::CYCLELINEAR;
else
// set a watch for the release of exactly these modifiers
fb->watchKeyRelease(*screen, mods);
FocusControl::FocusedWindows *win_list =
(options & FocusControl::CYCLELINEAR) ?
&screen->focusControl().creationOrderList() :
&screen->focusControl().focusedOrderList();
screen->focusControl().cycleFocus(win_list, m_option);
}
BScreen *screen = Fluxbox::instance()->keyScreen();
if (screen != 0)
screen->cycleFocus(m_option, false);
}
void PrevWindowCmd::execute() {
Fluxbox *fb = Fluxbox::instance();
BScreen *screen = fb->keyScreen();
if (screen != 0) {
// get modifiers from event that causes this for focus order cycling
unsigned int mods = 0;
XEvent ev = fb->lastEvent();
if (ev.type == KeyPress) {
mods = FbTk::KeyUtil::instance().cleanMods(ev.xkey.state);
} else if (ev.type == ButtonPress) {
mods = FbTk::KeyUtil::instance().cleanMods(ev.xbutton.state);
}
int options = m_option;
if (mods == 0) // can't stacked cycle unless there is a mod to grab
options |= FocusControl::CYCLELINEAR;
else
// set a watch for the release of exactly these modifiers
fb->watchKeyRelease(*screen, mods);
FocusControl::FocusedWindows *win_list =
(options & FocusControl::CYCLELINEAR) ?
&screen->focusControl().creationOrderList() :
&screen->focusControl().focusedOrderList();
screen->focusControl().cycleFocus(win_list, m_option, true);
}
BScreen *screen = Fluxbox::instance()->keyScreen();
if (screen != 0)
screen->cycleFocus(m_option, true);
}
void DirFocusCmd::execute() {

View file

@ -228,7 +228,6 @@ Fluxbox::Fluxbox(int argc, char **argv, const char *dpy_name, const char *rcfile
m_masked_window(0),
m_mousescreen(0),
m_keyscreen(0),
m_watching_screen(0), m_watch_keyrelease(0),
m_last_time(0),
m_masked(0),
m_rc_file(rcfilename ? rcfilename : ""),
@ -746,7 +745,6 @@ void Fluxbox::handleEvent(XEvent * const e) {
switch (e->type) {
case ButtonRelease:
case ButtonPress:
handleButtonEvent(e->xbutton);
break;
case ConfigureRequest: {
@ -894,7 +892,6 @@ void Fluxbox::handleEvent(XEvent * const e) {
break;
case KeyRelease:
case KeyPress:
handleKeyEvent(e->xkey);
break;
case ColormapNotify: {
BScreen *screen = searchScreen(e->xcolormap.window);
@ -958,20 +955,6 @@ void Fluxbox::handleEvent(XEvent * const e) {
}
}
void Fluxbox::handleButtonEvent(XButtonEvent &be) {
m_last_time = be.time;
BScreen *screen = searchScreen(be.window);
if (be.type == ButtonRelease || !screen)
// no bindings for this type yet
return;
if (be.button == 1 && !screen->isRootColormapInstalled())
screen->imageControl().installRootColormap();
m_key->doAction(be.type, be.state, be.button);
}
void Fluxbox::handleUnmapNotify(XUnmapEvent &ue) {
BScreen *screen = searchScreen(ue.event);
@ -1092,47 +1075,6 @@ void Fluxbox::handleClientMessage(XClientMessageEvent &ce) {
}
}
/**
Handles KeyRelease and KeyPress events
*/
void Fluxbox::handleKeyEvent(XKeyEvent &ke) {
if (keyScreen() == 0 || mouseScreen() == 0)
return;
switch (ke.type) {
case KeyPress:
m_key->doAction(ke.type, ke.state, ke.keycode);
break;
case KeyRelease: {
// we ignore most key releases unless we need to use
// a release to stop something (e.g. window cycling).
// we notify if _all_ of the watched modifiers are released
if (m_watching_screen && m_watch_keyrelease) {
// mask the mod of the released key out
// won't mask anything if it isn't a mod
unsigned int state = FbTk::KeyUtil::instance().isolateModifierMask(ke.state);
state &= ~FbTk::KeyUtil::instance().keycodeToModmask(ke.keycode);
if ((m_watch_keyrelease & state) == 0) {
m_watching_screen->notifyReleasedKeys();
XUngrabKeyboard(FbTk::App::instance()->display(), CurrentTime);
// once they are released, we drop the watch
m_watching_screen = 0;
m_watch_keyrelease = 0;
}
}
break;
}
default:
break;
}
}
/// handle system signals
void Fluxbox::handleSignal(int signum) {
_FB_USES_NLS;
@ -1810,28 +1752,6 @@ void Fluxbox::updateFocusedWindow(BScreen *screen, BScreen *old_screen) {
}
}
void Fluxbox::watchKeyRelease(BScreen &screen, unsigned int mods) {
if (mods == 0) {
cerr<<"WARNING: attempt to grab without modifiers!"<<endl;
return;
}
// just make sure we are saving the mods with any other flags (xkb)
m_watch_keyrelease = FbTk::KeyUtil::instance().isolateModifierMask(mods);
if (m_watching_screen == &screen)
return;
if (m_watching_screen)
m_watching_screen->focusControl().stopCyclingFocus();
m_watching_screen = &screen;
// TODO: it's possible (and happens to me sometimes) for the mods to be
// released before we grab the keyboard -- not sure of a good way to fix it
XGrabKeyboard(FbTk::App::instance()->display(),
screen.rootWindow().window(), True,
GrabModeAsync, GrabModeAsync, CurrentTime);
}
void Fluxbox::updateFrameExtents(FluxboxWindow &win) {
AtomHandlerContainerIt it = m_atomhandler.begin();
AtomHandlerContainerIt it_end = m_atomhandler.end();

View file

@ -141,8 +141,6 @@ public:
void maskWindowEvents(Window w, FluxboxWindow *bw)
{ m_masked = w; m_masked_window = bw; }
void watchKeyRelease(BScreen &screen, unsigned int mods);
void shutdown();
void load_rc(BScreen &scr);
void saveStyleFilename(const char *val) { m_rc_stylefile = (val == 0 ? "" : val); }
@ -203,8 +201,6 @@ public:
BScreen *mouseScreen() { return m_mousescreen; }
// screen of window that last key event (i.e. focused window) went to
BScreen *keyScreen() { return m_keyscreen; }
// screen we are watching for modifier changes
BScreen *watchingScreen() { return m_watching_screen; }
const XEvent &lastEvent() const { return m_last_event; }
AttentionNoticeHandler &attentionHandler() { return m_attention_handler; }
@ -228,10 +224,8 @@ private:
void handleEvent(XEvent *xe);
void setupConfigFiles();
void handleButtonEvent(XButtonEvent &be);
void handleUnmapNotify(XUnmapEvent &ue);
void handleClientMessage(XClientMessageEvent &ce);
void handleKeyEvent(XKeyEvent &ke);
std::auto_ptr<FbAtoms> m_fbatoms;
@ -272,8 +266,6 @@ private:
FluxboxWindow *m_masked_window;
BScreen *m_mousescreen, *m_keyscreen;
BScreen *m_watching_screen;
unsigned int m_watch_keyrelease;
Atom m_fluxbox_pid;