move titlebar click handling to FluxboxWindow, fix buttons getting ungrabbed

This commit is contained in:
markt 2007-11-20 19:01:45 +00:00
parent 2e96a07cf7
commit 08ebff4b31
9 changed files with 73 additions and 153 deletions

View file

@ -59,6 +59,7 @@ public:
virtual void enterNotifyEvent(XCrossingEvent &) { } virtual void enterNotifyEvent(XCrossingEvent &) { }
virtual void notifyUngrabKeyboard() { } virtual void notifyUngrabKeyboard() { }
virtual void grabButtons() { }
}; };
} // end namespace FbTk } // end namespace FbTk

View file

@ -96,7 +96,6 @@ FbWinFrame::FbWinFrame(BScreen &screen, FbWinFrameTheme &theme, FbTk::ImageContr
m_shaded(false), m_shaded(false),
m_focused_alpha(0), m_focused_alpha(0),
m_unfocused_alpha(0), m_unfocused_alpha(0),
m_double_click_time(0),
m_themelistener(*this), m_themelistener(*this),
m_shape(m_window, theme.shapePlace()), m_shape(m_window, theme.shapePlace()),
m_disable_themeshape(false) { m_disable_themeshape(false) {
@ -109,23 +108,6 @@ FbWinFrame::~FbWinFrame() {
removeAllButtons(); removeAllButtons();
} }
bool FbWinFrame::setOnClickTitlebar(FbTk::RefCount<FbTk::Command> &ref, int mousebutton_num,
bool double_click, bool pressed) {
// find mousebutton_num
if (mousebutton_num < 1 || mousebutton_num > 5)
return false;
if (double_click)
m_commands[mousebutton_num - 1].double_click = ref;
else {
if (pressed)
m_commands[mousebutton_num - 1].click_pressed = ref;
else
m_commands[mousebutton_num - 1].click = ref;
}
return true;
}
bool FbWinFrame::setTabMode(TabMode tabmode) { bool FbWinFrame::setTabMode(TabMode tabmode) {
if (m_tabmode == tabmode) if (m_tabmode == tabmode)
return false; return false;
@ -570,10 +552,6 @@ void FbWinFrame::setUseDefaultAlpha(bool default_alpha)
} }
} }
void FbWinFrame::setDoubleClickTime(unsigned int time) {
m_double_click_time = time;
}
void FbWinFrame::addLeftButton(FbTk::Button *btn) { void FbWinFrame::addLeftButton(FbTk::Button *btn) {
if (btn == 0) // valid button? if (btn == 0) // valid button?
return; return;
@ -685,7 +663,7 @@ void FbWinFrame::setClientWindow(FbTk::FbWindow &win) {
win.reparent(m_window, 0, clientArea().y()); win.reparent(m_window, 0, clientArea().y());
// remask window so we get events // remask window so we get events
win.setEventMask(PropertyChangeMask | StructureNotifyMask | win.setEventMask(PropertyChangeMask | StructureNotifyMask |
FocusChangeMask); FocusChangeMask | KeyPressMask);
m_window.setEventMask(ButtonPressMask | ButtonReleaseMask | m_window.setEventMask(ButtonPressMask | ButtonReleaseMask |
ButtonMotionMask | EnterWindowMask | SubstructureRedirectMask); ButtonMotionMask | EnterWindowMask | SubstructureRedirectMask);
@ -855,47 +833,6 @@ void FbWinFrame::removeEventHandler() {
evm.remove(m_clientarea); evm.remove(m_clientarea);
} }
void FbWinFrame::buttonPressEvent(XButtonEvent &event) {
m_tab_container.tryButtonPressEvent(event);
if (event.window == m_grip_right.window() ||
event.window == m_grip_left.window() ||
event.window == m_clientarea.window() ||
event.window == m_window.window())
return;
// we handle only buttons 0 to 5
if (event.button > 5 || event.button < 1)
return;
if (*m_commands[event.button - 1].click_pressed)
m_commands[event.button - 1].click_pressed->execute();
}
void FbWinFrame::buttonReleaseEvent(XButtonEvent &event) {
// we continue even if a button got the event
m_tab_container.tryButtonReleaseEvent(event);
if (event.window == m_grip_right.window() ||
event.window == m_grip_left.window() ||
event.window == m_clientarea.window() ||
event.window == m_handle.window() ||
event.window == m_window.window())
return;
if (event.button < 1 || event.button > 5)
return;
static Time last_release_time = 0;
bool double_click = (event.time - last_release_time <= m_double_click_time);
last_release_time = event.time;
int real_button = event.button - 1;
if (double_click && *m_commands[real_button].double_click)
m_commands[real_button].double_click->execute();
else if (*m_commands[real_button].click)
m_commands[real_button].click->execute();
}
void FbWinFrame::exposeEvent(XExposeEvent &event) { void FbWinFrame::exposeEvent(XExposeEvent &event) {
if (m_titlebar == event.window) { if (m_titlebar == event.window) {
m_titlebar.clearArea(event.x, event.y, event.width, event.height); m_titlebar.clearArea(event.x, event.y, event.width, event.height);
@ -1409,7 +1346,6 @@ void FbWinFrame::init() {
m_button_pm = m_button_unfocused_pm = m_button_pressed_pm = 0; m_button_pm = m_button_unfocused_pm = m_button_pressed_pm = 0;
m_grip_unfocused_pm = m_grip_focused_pm = 0; m_grip_unfocused_pm = m_grip_focused_pm = 0;
m_double_click_time = 200;
m_button_size = 26; m_button_size = 26;
m_clientarea.setBorderWidth(0); m_clientarea.setBorderWidth(0);

View file

@ -88,10 +88,6 @@ public:
/// destroy frame /// destroy frame
~FbWinFrame(); ~FbWinFrame();
/// setup actions for titlebar
bool setOnClickTitlebar(FbTk::RefCount<FbTk::Command> &cmd, int button_num,
bool double_click=false, bool pressed=false);
void hide(); void hide();
void show(); void show();
inline bool isVisible() const { return m_visible; } inline bool isVisible() const { return m_visible; }
@ -124,7 +120,6 @@ public:
/// set focus/unfocus style /// set focus/unfocus style
void setFocus(bool newvalue); void setFocus(bool newvalue);
inline void setFocusTitle(const std::string &str) { m_label.setText(str); } inline void setFocusTitle(const std::string &str) { m_label.setText(str); }
void setDoubleClickTime(unsigned int time);
bool setTabMode(TabMode tabmode); bool setTabMode(TabMode tabmode);
inline void updateTabProperties() { alignTabs(); } inline void updateTabProperties() { alignTabs(); }
@ -186,8 +181,6 @@ public:
@name Event handlers @name Event handlers
*/ */
//@{ //@{
void buttonPressEvent(XButtonEvent &event);
void buttonReleaseEvent(XButtonEvent &event);
void exposeEvent(XExposeEvent &event); void exposeEvent(XExposeEvent &event);
void configureNotifyEvent(XConfigureEvent &event); void configureNotifyEvent(XConfigureEvent &event);
void handleEvent(XEvent &event); void handleEvent(XEvent &event);
@ -377,13 +370,6 @@ private:
bool m_shaded; ///< wheter we're shaded or not bool m_shaded; ///< wheter we're shaded or not
unsigned char m_focused_alpha; ///< focused alpha value unsigned char m_focused_alpha; ///< focused alpha value
unsigned char m_unfocused_alpha; ///< unfocused alpha value unsigned char m_unfocused_alpha; ///< unfocused alpha value
unsigned int m_double_click_time; ///< the time period that's considerd to be a double click
struct MouseButtonAction {
FbTk::RefCount<FbTk::Command> click; ///< what to do when we release mouse button
FbTk::RefCount<FbTk::Command> click_pressed; ///< what to do when we press mouse button
FbTk::RefCount<FbTk::Command> double_click; ///< what to do when we double click
};
MouseButtonAction m_commands[5]; ///< hardcoded to five ... //!! TODO, change this
class ThemeListener: public FbTk::Observer { class ThemeListener: public FbTk::Observer {
public: public:

View file

@ -126,11 +126,11 @@ void FocusableList::update(FbTk::Subject *subj) {
FocusableListSubject *fsubj = FocusableListSubject *fsubj =
static_cast<FocusableListSubject *>(subj); static_cast<FocusableListSubject *>(subj);
if (subj == &m_parent->addSig()) { if (subj == &m_parent->addSig()) {
attachSignals(*fsubj->win());
if (m_pat->match(*fsubj->win())) { if (m_pat->match(*fsubj->win())) {
insertFromParent(*fsubj->win()); insertFromParent(*fsubj->win());
m_addsig.notify(fsubj->win()); m_addsig.notify(fsubj->win());
} else // we still want to watch it, in case it changes to match }
attachSignals(*fsubj->win());
} else if (subj == &m_parent->removeSig()) } else if (subj == &m_parent->removeSig())
remove(*fsubj->win()); remove(*fsubj->win());
else if (subj == &m_parent->resetSig()) else if (subj == &m_parent->resetSig())

View file

@ -168,6 +168,7 @@ void Keys::grabWindow(Window win) {
if (win_it == m_window_map.end()) if (win_it == m_window_map.end())
return; return;
m_handler_map[win]->grabButtons();
keylist_t::iterator it = m_keylist->keylist.begin(); keylist_t::iterator it = m_keylist->keylist.begin();
keylist_t::iterator it_end = m_keylist->keylist.end(); keylist_t::iterator it_end = m_keylist->keylist.end();
for (; it != it_end; ++it) { for (; it != it_end; ++it) {
@ -428,8 +429,9 @@ bool Keys::doAction(int type, unsigned int mods, unsigned int key,
} }
/// adds the window to m_window_map, so we know to grab buttons on it /// adds the window to m_window_map, so we know to grab buttons on it
void Keys::registerWindow(Window win, int context) { void Keys::registerWindow(Window win, FbTk::EventHandler &h, int context) {
m_window_map[win] = context; m_window_map[win] = context;
m_handler_map[win] = &h;
grabWindow(win); grabWindow(win);
} }
@ -437,6 +439,7 @@ void Keys::registerWindow(Window win, int context) {
void Keys::unregisterWindow(Window win) { void Keys::unregisterWindow(Window win) {
FbTk::KeyUtil::ungrabKeys(win); FbTk::KeyUtil::ungrabKeys(win);
FbTk::KeyUtil::ungrabButtons(win); FbTk::KeyUtil::ungrabButtons(win);
m_handler_map.erase(win);
m_window_map.erase(win); m_window_map.erase(win);
} }
@ -459,6 +462,13 @@ void Keys::keyMode(string keyMode) {
void Keys::setKeyMode(t_key *keyMode) { void Keys::setKeyMode(t_key *keyMode) {
ungrabKeys(); ungrabKeys();
ungrabButtons(); ungrabButtons();
// notify handlers that their buttons have been ungrabbed
HandlerMap::iterator h_it = m_handler_map.begin(),
h_it_end = m_handler_map.end();
for (; h_it != h_it_end; ++h_it)
h_it->second->grabButtons();
keylist_t::iterator it = keyMode->keylist.begin(); keylist_t::iterator it = keyMode->keylist.begin();
keylist_t::iterator it_end = keyMode->keylist.end(); keylist_t::iterator it_end = keyMode->keylist.end();
for (; it != it_end; ++it) { for (; it != it_end; ++it) {

View file

@ -34,6 +34,10 @@
#include "FbTk/Command.hh" #include "FbTk/Command.hh"
#include "FbTk/KeyUtil.hh" #include "FbTk/KeyUtil.hh"
namespace FbTk {
class EventHandler;
}
class Keys:private FbTk::NotCopyable { class Keys:private FbTk::NotCopyable {
public: public:
@ -78,7 +82,7 @@ public:
bool doAction(int type, unsigned int mods, unsigned int key, int context); bool doAction(int type, unsigned int mods, unsigned int key, int context);
/// register a window so that proper keys/buttons get grabbed on it /// register a window so that proper keys/buttons get grabbed on it
void registerWindow(Window win, int context); void registerWindow(Window win, FbTk::EventHandler &handler, int context);
/// unregister window /// unregister window
void unregisterWindow(Window win); void unregisterWindow(Window win);
@ -145,7 +149,9 @@ private:
Display *m_display; ///< display connection Display *m_display; ///< display connection
typedef std::map<Window, int> WindowMap; typedef std::map<Window, int> WindowMap;
typedef std::map<Window, FbTk::EventHandler*> HandlerMap;
WindowMap m_window_map; WindowMap m_window_map;
HandlerMap m_handler_map;
}; };
#endif // KEYS_HH #endif // KEYS_HH

View file

@ -431,7 +431,7 @@ BScreen::BScreen(FbTk::ResourceManager &rm,
evm->add(*this, rootWindow()); evm->add(*this, rootWindow());
Keys *keys = Fluxbox::instance()->keys(); Keys *keys = Fluxbox::instance()->keys();
if (keys) if (keys)
keys->registerWindow(rootWindow().window(), keys->registerWindow(rootWindow().window(), *this,
Keys::GLOBAL|Keys::ON_DESKTOP); Keys::GLOBAL|Keys::ON_DESKTOP);
rootWindow().setCursor(XCreateFontCursor(disp, XC_left_ptr)); rootWindow().setCursor(XCreateFontCursor(disp, XC_left_ptr));

View file

@ -280,7 +280,7 @@ Toolbar::Toolbar(BScreen &scrn, FbTk::XLayer &layer, size_t width):
scrn.resourceManager().unlock(); scrn.resourceManager().unlock();
// setup to listen to child events // setup to listen to child events
FbTk::EventManager::instance()->addParent(*this, window()); FbTk::EventManager::instance()->addParent(*this, window());
Fluxbox::instance()->keys()->registerWindow(window().window(), Fluxbox::instance()->keys()->registerWindow(window().window(), *this,
Keys::ON_TOOLBAR); Keys::ON_TOOLBAR);
// get everything together // get everything together
reconfigure(); reconfigure();

View file

@ -289,7 +289,7 @@ FluxboxWindow::FluxboxWindow(WinClient &client, FbWinFrameTheme &tm,
screen().focusControl().addFocusWinBack(*this); screen().focusControl().addFocusWinBack(*this);
Fluxbox::instance()->keys()->registerWindow(frame().window().window(), Fluxbox::instance()->keys()->registerWindow(frame().window().window(),
Keys::ON_WINDOW); *this, Keys::ON_WINDOW);
} }
@ -479,8 +479,6 @@ void FluxboxWindow::init() {
applyDecorations(true); applyDecorations(true);
grabButtons();
restoreAttributes(); restoreAttributes();
if (m_workspace_number >= screen().numberOfWorkspaces()) if (m_workspace_number >= screen().numberOfWorkspaces())
@ -1062,9 +1060,6 @@ void FluxboxWindow::reconfigure() {
moveResize(frame().x(), frame().y(), frame().width(), frame().height()); moveResize(frame().x(), frame().y(), frame().width(), frame().height());
grabButtons();
frame().setDoubleClickTime(Fluxbox::instance()->getDoubleClickInterval());
m_timer.setTimeout(Fluxbox::instance()->getAutoRaiseDelay()); m_timer.setTimeout(Fluxbox::instance()->getAutoRaiseDelay());
updateButtons(); updateButtons();
@ -1072,29 +1067,6 @@ void FluxboxWindow::reconfigure() {
menu().reconfigure(); menu().reconfigure();
typedef FbTk::RefCount<FbTk::Command> CommandRef;
typedef FbTk::SimpleCommand<FluxboxWindow> WindowCmd;
CommandRef shade_on_cmd(new WindowCmd(*this, &FluxboxWindow::shadeOn));
CommandRef shade_off_cmd(new WindowCmd(*this, &FluxboxWindow::shadeOff));
CommandRef next_tab_cmd(new WindowCmd(*this, &FluxboxWindow::nextClient));
CommandRef prev_tab_cmd(new WindowCmd(*this, &FluxboxWindow::prevClient));
CommandRef null_cmd;
int reverse = 0;
if (screen().getScrollReverse())
reverse = 1;
if (StringUtil::toLower(screen().getScrollAction()) == string("shade")) {
frame().setOnClickTitlebar(shade_on_cmd, 5 - reverse); // shade on mouse roll
frame().setOnClickTitlebar(shade_off_cmd, 4 + reverse); // unshade if rolled oposite direction
} else if (StringUtil::toLower(screen().getScrollAction()) == string("nexttab")) {
frame().setOnClickTitlebar(next_tab_cmd, 5 - reverse); // next tab
frame().setOnClickTitlebar(prev_tab_cmd, 4 + reverse); // previous tab
} else {
frame().setOnClickTitlebar(null_cmd, 4);
frame().setOnClickTitlebar(null_cmd, 5);
}
Client2ButtonMap::iterator it = m_labelbuttons.begin(), Client2ButtonMap::iterator it = m_labelbuttons.begin(),
it_end = m_labelbuttons.end(); it_end = m_labelbuttons.end();
for (; it != it_end; ++it) for (; it != it_end; ++it)
@ -2584,14 +2556,20 @@ void FluxboxWindow::buttonPressEvent(XButtonEvent &be) {
return; return;
} }
// check frame events first frame().tabcontainer().tryButtonPressEvent(be);
frame().buttonPressEvent(be);
if (be.button == 1) { if (be.button == 1) {
if (!m_focused && acceptsFocus()) //check focus if (!m_focused && acceptsFocus()) //check focus
focus(); focus();
if (frame().window().window() == be.window || frame().tabcontainer().window() == be.window) { // click on titlebar
if (frame().gripLeft().window() != be.window &&
frame().gripRight().window() != be.window &&
frame().clientArea().window() != be.window &&
frame().window() != be.window)
raise();
if (frame().window().window() == be.window ||
frame().tabcontainer().window() == be.window) {
if (screen().clickRaises()) if (screen().clickRaises())
raise(); raise();
#ifdef DEBUG #ifdef DEBUG
@ -2618,8 +2596,44 @@ void FluxboxWindow::buttonReleaseEvent(XButtonEvent &re) {
stopResizing(); stopResizing();
else if (m_attaching_tab) else if (m_attaching_tab)
attachTo(re.x_root, re.y_root); attachTo(re.x_root, re.y_root);
else {
frame().tabcontainer().tryButtonReleaseEvent(re);
if (frame().gripLeft().window() == re.window ||
frame().gripRight().window() == re.window ||
frame().clientArea().window() == re.window ||
frame().handle().window() == re.window ||
frame().window() == re.window)
return;
static Time last_release_time = 0;
bool double_click = (re.time - last_release_time <=
Fluxbox::instance()->getDoubleClickInterval());
last_release_time = re.time;
if (re.button == 1 && double_click)
shade();
if (re.button == 3)
popupMenu();
if (re.button == 2)
lower();
unsigned int reverse = (screen().getScrollReverse() ? 1 : 0);
if (re.button == 4 || re.button == 5) {
if (StringUtil::toLower(screen().getScrollAction()) == "shade") {
if (re.button == 5 - reverse)
shadeOn();
else else
frame().buttonReleaseEvent(re); shadeOff();
}
if (StringUtil::toLower(screen().getScrollAction()) == "nexttab") {
if (re.button == 5 - reverse)
nextClient();
else
prevClient();
}
}
}
} }
@ -3774,19 +3788,6 @@ void FluxboxWindow::setupWindow() {
// we allow both to be done at once to share the commands // we allow both to be done at once to share the commands
using namespace FbTk; using namespace FbTk;
typedef RefCount<Command> CommandRef;
typedef SimpleCommand<FluxboxWindow> WindowCmd;
CommandRef shade_cmd(new WindowCmd(*this, &FluxboxWindow::shade));
CommandRef shade_on_cmd(new WindowCmd(*this, &FluxboxWindow::shadeOn));
CommandRef shade_off_cmd(new WindowCmd(*this, &FluxboxWindow::shadeOff));
CommandRef next_tab_cmd(new WindowCmd(*this, &FluxboxWindow::nextClient));
CommandRef prev_tab_cmd(new WindowCmd(*this, &FluxboxWindow::prevClient));
CommandRef lower_cmd(new WindowCmd(*this, &FluxboxWindow::lower));
CommandRef raise_and_focus_cmd(new WindowCmd(*this, &FluxboxWindow::raiseAndFocus));
CommandRef stick_cmd(new WindowCmd(*this, &FluxboxWindow::stick));
CommandRef show_menu_cmd(new WindowCmd(*this, &FluxboxWindow::popupMenu));
typedef FbTk::Resource<vector<WinButton::Type> > WinButtonsResource; typedef FbTk::Resource<vector<WinButton::Type> > WinButtonsResource;
string titlebar_name[2]; string titlebar_name[2];
@ -3842,26 +3843,6 @@ void FluxboxWindow::setupWindow() {
updateButtons(); updateButtons();
// setup titlebar
frame().setOnClickTitlebar(raise_and_focus_cmd, 1, false, true); // on press with button 1
frame().setOnClickTitlebar(shade_cmd, 1, true); // doubleclick with button 1
frame().setOnClickTitlebar(show_menu_cmd, 3); // on release with button 3
frame().setOnClickTitlebar(lower_cmd, 2); // on release with button 2
int reverse = 0;
if (screen().getScrollReverse())
reverse = 1;
if (StringUtil::toLower(screen().getScrollAction()) == string("shade")) {
frame().setOnClickTitlebar(shade_on_cmd, 5 - reverse); // shade on mouse roll
frame().setOnClickTitlebar(shade_off_cmd, 4 + reverse); // unshade if rolled oposite direction
} else if (StringUtil::toLower(screen().getScrollAction()) == string("nexttab")) {
frame().setOnClickTitlebar(next_tab_cmd, 5 - reverse); // next tab
frame().setOnClickTitlebar(prev_tab_cmd, 4 + reverse); // previous tab
}
frame().setDoubleClickTime(Fluxbox::instance()->getDoubleClickInterval());
// end setup frame // end setup frame
} }