various refactoring and minor changes

This commit is contained in:
markt 2007-11-05 17:05:58 +00:00
parent 2c4e1f9a02
commit 97f7c3e1b5
9 changed files with 182 additions and 243 deletions

View file

@ -214,19 +214,9 @@ void Ewmh::setupClient(WinClient &winclient) {
updateStrut(winclient);
FbTk::FbString newtitle = winclient.textProperty(m_net_wm_name);
if (!newtitle.empty()) {
if (!newtitle.empty())
winclient.setTitle(newtitle);
}
newtitle = winclient.textProperty(m_net_wm_icon_name);
if (!newtitle.empty()) {
winclient.setIconTitle(newtitle);
}
if ( winclient.fbwindow() )
winclient.fbwindow()->titleSig().notify();
}
void Ewmh::setupFrame(FluxboxWindow &win) {
Atom ret_type;
int fmt;
unsigned long nitems, bytes_after;
@ -248,95 +238,59 @@ void Ewmh::setupFrame(FluxboxWindow &win) {
*
*/
win.winClient().property(m_net_wm_window_type, 0, 0x7fffffff, False, XA_ATOM,
winclient.property(m_net_wm_window_type, 0, 0x7fffffff, False, XA_ATOM,
&ret_type, &fmt, &nitems, &bytes_after,
&data);
Focusable::WindowType type = Focusable::TYPE_NORMAL;
if (data) {
Atom *atoms = (unsigned long *)data;
for (unsigned long l = 0; l < nitems; ++l) {
/* From Extended Window Manager Hints, draft 1.3:
*
* _NET_WM_WINDOW_TYPE_DOCK indicates a dock or panel feature.
* Typically a Window Manager would keep such windows on top
* of all other windows.
*
*/
if (atoms[l] == m_net_wm_window_type_dock) {
// we also assume it shouldn't be visible in any toolbar
win.setFocusHidden(true);
win.setIconHidden(true);
win.setDecorationMask(FluxboxWindow::DECOR_NONE);
win.moveToLayer(Layer::DOCK);
} else if (atoms[l] == m_net_wm_window_type_desktop) {
/*
* _NET_WM_WINDOW_TYPE_DESKTOP indicates a "false desktop" window
* We let it be the size it wants, but it gets no decoration,
* is hidden in the toolbar and window cycling list, plus
* windows don't tab with it and is right on the bottom.
*/
win.setFocusHidden(true);
win.setIconHidden(true);
win.moveToLayer(Layer::DESKTOP);
win.setDecorationMask(FluxboxWindow::DECOR_NONE);
win.setTabable(false);
win.setMovable(false);
win.setResizable(false);
win.stick();
} else if (atoms[l] == m_net_wm_window_type_splash) {
/*
* _NET_WM_WINDOW_TYPE_SPLASH indicates that the
* window is a splash screen displayed as an application
* is starting up.
*/
win.setDecorationMask(FluxboxWindow::DECOR_NONE);
win.setFocusHidden(true);
win.setIconHidden(true);
win.setMovable(false);
} else if (atoms[l] == m_net_wm_window_type_normal) {
// do nothing, this is ..normal..
} else if (atoms[l] == m_net_wm_window_type_dialog) {
// dialog windows should not be tabable
win.setTabable(false);
} else if (atoms[l] == m_net_wm_window_type_menu) {
/*
* _NET_WM_WINDOW_TYPE_TOOLBAR and _NET_WM_WINDOW_TYPE_MENU
* indicate toolbar and pinnable menu windows, respectively
* (i.e. toolbars and menus "torn off" from the main
* application). Windows of this type may set the
* WM_TRANSIENT_FOR hint indicating the main application window.
*/
win.setDecorationMask(FluxboxWindow::DECOR_TOOL);
win.setIconHidden(true);
win.moveToLayer(Layer::ABOVE_DOCK);
} else if (atoms[l] == m_net_wm_window_type_toolbar) {
win.setDecorationMask(FluxboxWindow::DECOR_NONE);
win.setIconHidden(true);
win.moveToLayer(Layer::ABOVE_DOCK);
}
}
XFree(data);
} else {
// if _NET_WM_WINDOW_TYPE not set and this window
// has transient_for the type must be set to _NET_WM_WINDOW_TYPE_DIALOG
if ( win.winClient().isTransient() ) {
win.winClient().
changeProperty(m_net_wm_window_type,
XA_ATOM, 32, PropModeReplace,
(unsigned char*)&m_net_wm_window_type_dialog, 1);
// and then we should treat it like a dialog
win.setTabable(false);
}
}
if (atoms[l] == m_net_wm_window_type_dock)
type = Focusable::TYPE_DOCK;
else if (atoms[l] == m_net_wm_window_type_desktop)
type = Focusable::TYPE_DESKTOP;
else if (atoms[l] == m_net_wm_window_type_splash)
type = Focusable::TYPE_SPLASH;
else if (atoms[l] == m_net_wm_window_type_dialog)
type = Focusable::TYPE_DIALOG;
else if (atoms[l] == m_net_wm_window_type_menu)
type = Focusable::TYPE_MENU;
else if (atoms[l] == m_net_wm_window_type_toolbar)
type = Focusable::TYPE_TOOLBAR;
else if (atoms[l] != m_net_wm_window_type_normal)
continue;
/*
* NOT YET IMPLEMENTED:
* _NET_WM_WINDOW_TYPE_UTILITY
*/
break;
}
XFree(data);
} else if (winclient.isTransient()) {
// if _NET_WM_WINDOW_TYPE not set and this window
// has transient_for the type must be set to _NET_WM_WINDOW_TYPE_DIALOG
if (winclient.isTransient()) {
type = Focusable::TYPE_DIALOG;
winclient.
changeProperty(m_net_wm_window_type,
XA_ATOM, 32, PropModeReplace,
(unsigned char*)&m_net_wm_window_type_dialog, 1);
}
}
winclient.setWindowType(type);
}
void Ewmh::setupFrame(FluxboxWindow &win) {
setupState(win);
Atom ret_type;
int fmt;
unsigned long nitems, bytes_after;
unsigned char *data = 0;
if (win.winClient().property(m_net_wm_desktop, 0, 1, False, XA_CARDINAL,
&ret_type, &fmt, &nitems, &bytes_after,
(unsigned char **) &data) && data) {
@ -929,11 +883,7 @@ bool Ewmh::propertyNotify(WinClient &winclient, Atom the_property) {
winclient.fbwindow()->titleSig().notify();
return true;
} else if (the_property == m_net_wm_icon_name) {
FbTk::FbString newtitle = winclient.textProperty(the_property);
if (!newtitle.empty())
winclient.setIconTitle(newtitle);
if (winclient.fbwindow())
winclient.fbwindow()->titleSig().notify();
// we don't use icon title, since we don't show icons
return true;
}

View file

@ -167,32 +167,17 @@ void FocusControl::cycleFocus(const Focusables &window_list,
void FocusControl::goToWindowNumber(const Focusables &winlist, int num,
const ClientPattern *pat) {
Focusable *last_matched = 0;
if (num > 0) {
Focusables::const_iterator it = winlist.begin();
Focusables::const_iterator it_end = winlist.end();
for (; it != it_end; ++it) {
for (; it != it_end && num; ++it) {
if (!doSkipWindow(**it, pat) && (*it)->acceptsFocus()) {
--num;
last_matched = *it;
if (!num) break;
num > 0 ? --num : ++num;
if (!num) {
(*it)->focus();
if ((*it)->fbwindow())
(*it)->fbwindow()->raise();
}
}
} else if (num < 0) {
Focusables::const_reverse_iterator it = winlist.rbegin();
Focusables::const_reverse_iterator it_end = winlist.rend();
for (; it != it_end; ++it) {
if (!doSkipWindow(**it, pat) && (*it)->acceptsFocus()) {
++num;
last_matched = *it;
if (!num) break;
}
}
}
if (last_matched) {
last_matched->focus();
if (last_matched->fbwindow())
last_matched->fbwindow()->raise();
}
}
@ -371,7 +356,7 @@ void FocusControl::dirFocus(FluxboxWindow &win, FocusDir dir) {
if ((*it) == &win
|| (*it)->isIconic()
|| (*it)->isFocusHidden()
|| !(*it)->winClient().acceptsFocus())
|| !(*it)->acceptsFocus())
continue; // skip self
// we check things against an edge, and within the bounds (draw a picture)

View file

@ -46,6 +46,17 @@ public:
m_titlesig(*this), m_focussig(*this), m_diesig(*this),
m_attentionsig(*this) { }
virtual ~Focusable() { }
enum WindowType {
TYPE_NORMAL,
TYPE_DOCK,
TYPE_DESKTOP,
TYPE_SPLASH,
TYPE_DIALOG,
TYPE_MENU,
TYPE_TOOLBAR
};
/**
* Take focus.
* @return true if the focuable took focus
@ -87,6 +98,9 @@ public:
/// @return wm role string (for pattern matching)
virtual std::string getWMRole() const { return "Focusable"; }
/// @return window type
virtual WindowType getWindowType() const { return TYPE_NORMAL; }
/// @return whether this window is a transient (for pattern matching)
virtual bool isTransient() const { return false; }

View file

@ -390,6 +390,11 @@ bool Keys::doAction(int type, unsigned int mods, unsigned int key,
// grab "None Escape" to exit keychain in the middle
unsigned int esc = FbTk::KeyUtil::getKey("Escape");
// if focus changes, windows will get NotifyWhileGrabbed,
// which they tend to ignore
if (temp_key && type == KeyPress)
XUngrabKeyboard(Fluxbox::instance()->display(), CurrentTime);
if (temp_key && !temp_key->keylist.empty()) { // emacs-style
if (!saved_keymode)
saved_keymode = m_keylist;

View file

@ -79,13 +79,13 @@ WinClient::WinClient(Window win, BScreen &screen, FluxboxWindow *fbwin):
wm_hint_flags(0),
m_modal_count(0),
m_modal(false),
accepts_input(false),
send_focus_message(false),
send_close_message(false),
m_win_gravity(0),
m_title_override(false),
m_icon_title_override(false),
m_window_type(Focusable::TYPE_NORMAL),
m_mwm_hint(0),
m_focus_mode(F_PASSIVE),
m_strut(0) {
updateWMProtocols();
updateMWMHints();
@ -93,7 +93,6 @@ WinClient::WinClient(Window win, BScreen &screen, FluxboxWindow *fbwin):
updateWMNormalHints();
updateWMClassHint();
updateTitle();
updateIconTitle();
Fluxbox::instance()->saveWindowSearch(win, this);
if (window_group != None)
Fluxbox::instance()->saveGroupSearch(window_group, this);
@ -167,11 +166,17 @@ WinClient::~WinClient() {
}
bool WinClient::acceptsFocus() const {
return (m_focus_mode == F_LOCALLYACTIVE ||
m_focus_mode == F_PASSIVE);
return ((accepts_input || send_focus_message) &&
// focusing fbpanel messes up quite a few things
m_window_type != Focusable::TYPE_DOCK &&
m_window_type != Focusable::TYPE_SPLASH);
}
bool WinClient::sendFocus() {
if (accepts_input) {
setInputFocus(RevertToParent, CurrentTime);
return true;
}
if (!send_focus_message)
return false;
#ifdef DEBUG
@ -236,12 +241,6 @@ string WinClient::getWMRole() const {
return textProperty(wm_role);
}
const string &WinClient::title() const {
if (!fbwindow() || !fbwindow()->isIconic() || m_icon_title.empty())
return m_title;
return m_icon_title;
}
void WinClient::updateWMClassHint() {
XClassHint ch;
if (XGetClassHint(display(), window(), &ch) == 0) {
@ -369,48 +368,6 @@ void WinClient::setTitle(FbTk::FbString &title) {
fbwindow()->updateTitleFromClient(*this);
}
void WinClient::setIconTitle(FbTk::FbString &icon_title) {
m_icon_title = icon_title;
m_icon_title_override = true;
if (fbwindow() && fbwindow()->isIconic())
fbwindow()->updateTitleFromClient(*this);
}
void WinClient::updateIconTitle() {
if (m_icon_title_override)
return;
XTextProperty text_prop;
char **list = 0;
int num = 0;
if (getWMIconName(text_prop)) {
if (text_prop.value && text_prop.nitems > 0) {
if (text_prop.encoding != XA_STRING) {
text_prop.nitems = strlen((char *) text_prop.value);
XmbTextPropertyToTextList(display(), &text_prop, &list, &num);
if (num > 0 && list)
m_icon_title = (char *)*list;
else
m_icon_title = text_prop.value ? (char *)text_prop.value : "";
if (list)
XFreeStringList(list);
} else
m_icon_title = text_prop.value ? (char *)text_prop.value : "";
if (text_prop.value)
XFree((char *) text_prop.value);
} else
m_icon_title = "";
} else
m_icon_title = "";
if (fbwindow() && fbwindow()->isIconic())
fbwindow()->updateTitleFromClient(*this);
}
void WinClient::saveBlackboxAttribs(FluxboxWindow::BlackboxAttributes &blackbox_attribs) {
changeProperty(FbAtoms::instance()->getFluxboxAttributesAtom(),
XA_CARDINAL, 32, PropModeReplace,
@ -450,11 +407,10 @@ void WinClient::updateMWMHints() {
void WinClient::updateWMHints() {
XWMHints *wmhint = XGetWMHints(display(), window());
if (! wmhint) {
m_focus_mode = F_PASSIVE;
accepts_input = true;
window_group = None;
initial_state = NormalState;
} else {
if (wmhint) {
wm_hint_flags = wmhint->flags;
/*
* ICCCM 4.1.7
@ -467,34 +423,16 @@ void WinClient::updateWMHints() {
* Globally Active False Present
*---------------------------------------------
* Here: WM_TAKE_FOCUS = send_focus_message
* Input Field = wmhint->input
* Input Model = m_focus_mode
* Input Field = accepts_input
*/
if (wmhint->flags & InputHint) {
if (wmhint->input) {
if (send_focus_message)
m_focus_mode = F_LOCALLYACTIVE;
else
m_focus_mode = F_PASSIVE;
} else {
if (send_focus_message)
m_focus_mode = F_GLOBALLYACTIVE;
else
m_focus_mode = F_NOINPUT;
}
} else // InputHint not present: ignoring send_focus_message and assuming F_PASSIVE
m_focus_mode = F_PASSIVE;
if (wmhint->flags & InputHint)
accepts_input = (bool)wmhint->input;
if (wmhint->flags & StateHint)
initial_state = wmhint->initial_state;
else
initial_state = NormalState;
if (wmhint->flags & WindowGroupHint) {
if (! window_group)
if (wmhint->flags & WindowGroupHint && !window_group)
window_group = wmhint->window_group;
} else
window_group = None;
if ((bool)(wmhint->flags & IconPixmapHint) && wmhint->icon_pixmap != 0)
m_icon.pixmap().copy(wmhint->icon_pixmap, 0, 0);

View file

@ -64,9 +64,7 @@ public:
// override the title with this
void setTitle(FbTk::FbString &title);
void setIconTitle(FbTk::FbString &icon_title);
void updateTitle();
void updateIconTitle();
/// updates transient window information
void updateTransientInfo();
@ -80,7 +78,7 @@ public:
bool focus(); // calls Window->setCurrentClient to give focus to this client
bool isFocused() const;
void setAttentionState(bool value);
const std::string &title() const;
const std::string &title() const { return m_title; }
/**
* Changes width and height to the nearest (lower) value
@ -110,6 +108,8 @@ public:
bool getWMName(XTextProperty &textprop) const;
bool getWMIconName(XTextProperty &textprop) const;
std::string getWMRole() const;
Focusable::WindowType getWindowType() const { return m_window_type; }
void setWindowType(Focusable::WindowType type) { m_window_type = type; }
inline WinClient *transientFor() { return transient_for; }
inline const WinClient *transientFor() const { return transient_for; }
@ -127,7 +127,6 @@ public:
// grouping is tracked by remembering the window to the left in the group
Window getGroupLeftWindow() const;
inline int getFocusMode() const { return m_focus_mode; }
inline const MwmHints *getMwmHint() const { return m_mwm_hint; }
inline unsigned int maxWidth() const { return max_width; }
@ -152,9 +151,6 @@ public:
base_width, base_height;
unsigned long initial_state, normal_hint_flags, wm_hint_flags;
enum FocusMode { F_NOINPUT = 0, F_PASSIVE, F_LOCALLYACTIVE, F_GLOBALLYACTIVE };
private:
/// removes client from any waiting list and clears empty waiting lists
void removeTransientFromWaitingList();
@ -167,17 +163,15 @@ private:
// number of transients which we are modal for
int m_modal_count;
bool m_modal;
bool send_focus_message, send_close_message;
bool accepts_input, send_focus_message, send_close_message;
int m_win_gravity;
std::string m_icon_title;
bool m_title_override, m_icon_title_override;
bool m_title_override;
Focusable::WindowType m_window_type;
MwmHints *m_mwm_hint;
int m_focus_mode;
Strut *m_strut;
// map transient_for X window to winclient transient
// (used if transient_for FbWindow was created after transient)

View file

@ -453,6 +453,8 @@ void FluxboxWindow::init() {
wattrib.width, wattrib.height,
m_client->gravity(), m_client->old_bw);
setWindowType(m_client->getWindowType());
if (fluxbox.isStartup())
m_placed = true;
else if (m_client->isTransient() ||
@ -1021,7 +1023,6 @@ void FluxboxWindow::associateClientWindow(bool use_attrs,
unsigned int width, unsigned int height,
int gravity, unsigned int client_bw) {
m_client->updateTitle();
m_client->updateIconTitle();
frame().setShapingClient(m_client, false);
@ -1353,26 +1354,7 @@ bool FluxboxWindow::focus() {
if (m_client->isModal())
return false;
bool ret = false;
if (m_client->acceptsFocus()) {
m_client->setInputFocus(RevertToParent, CurrentTime);
FbTk::App *app = FbTk::App::instance();
XFlush(app->display());
m_client->sendFocus();
app->sync(false);
ret = true;
} else {
ret = m_client->sendFocus();
}
return ret;
return m_client->sendFocus();
}
// don't hide the frame directly, use this function
@ -2129,14 +2111,6 @@ void FluxboxWindow::restoreAttributes() {
m_layernum = m_blackbox_attrib.stack;
}
if ((m_blackbox_attrib.flags & ATTRIB_MAXHORIZ) ||
(m_blackbox_attrib.flags & ATTRIB_MAXVERT)) {
m_blackbox_attrib.premax_x = m_blackbox_attrib.premax_x;
m_blackbox_attrib.premax_y = m_blackbox_attrib.premax_y;
m_blackbox_attrib.premax_w = m_blackbox_attrib.premax_w;
m_blackbox_attrib.premax_h = m_blackbox_attrib.premax_h;
}
}
/**
@ -2369,8 +2343,9 @@ void FluxboxWindow::propertyNotifyEvent(WinClient &client, Atom atom) {
break;
case XA_WM_ICON_NAME:
// update icon title and then do normal XA_WM_NAME stuff
client.updateIconTitle();
// we don't use icon title, since many apps don't update it,
// and we don't show icons anyway
break;
case XA_WM_NAME:
client.updateTitle();
break;
@ -2610,7 +2585,7 @@ void FluxboxWindow::buttonPressEvent(XButtonEvent &be) {
frame().buttonPressEvent(be);
if (be.button == 1) {
if (!m_focused) //check focus
if (!m_focused && acceptsFocus()) //check focus
focus();
if (frame().window().window() == be.window || frame().tabcontainer().window() == be.window) {
@ -2968,7 +2943,8 @@ void FluxboxWindow::enterNotifyEvent(XCrossingEvent &ev) {
ev.window == m_client->window() ||
client) {
if (screen().focusControl().isMouseFocus() && !isFocused()) {
if (screen().focusControl().isMouseFocus() && !isFocused() &&
acceptsFocus() && getWindowType() != Focusable::TYPE_DESKTOP) {
// check that there aren't any subsequent leave notify events in the
// X event queue
@ -3138,7 +3114,6 @@ void FluxboxWindow::startMoving(int x, int y) {
m_button_grab_y = y - frame().y() - frame().window().borderWidth();
moving = true;
maximized = MAX_NONE;
Fluxbox *fluxbox = Fluxbox::instance();
// grabbing (and masking) on the root window allows us to
@ -3674,6 +3649,10 @@ std::string FluxboxWindow::getWMRole() const {
return (m_client ? m_client->getWMRole() : "FluxboxWindow");
}
Focusable::WindowType FluxboxWindow::getWindowType() const {
return (m_client ? m_client->getWindowType() : Focusable::TYPE_NORMAL);
}
bool FluxboxWindow::isTransient() const {
return (m_client && m_client->isTransient());
}
@ -4139,3 +4118,72 @@ void FluxboxWindow::placeWindow(int head) {
screen().placementStrategy().placeWindow(*this, head, place_x, place_y);
move(place_x, place_y);
}
void FluxboxWindow::setWindowType(Focusable::WindowType type) {
switch (type) {
case Focusable::TYPE_DOCK:
/* From Extended Window Manager Hints, draft 1.3:
*
* _NET_WM_WINDOW_TYPE_DOCK indicates a dock or panel feature.
* Typically a Window Manager would keep such windows on top
* of all other windows.
*
*/
setFocusHidden(true);
setIconHidden(true);
setDecorationMask(DECOR_NONE);
moveToLayer(::Layer::DOCK);
break;
case Focusable::TYPE_DESKTOP:
/*
* _NET_WM_WINDOW_TYPE_DESKTOP indicates a "false desktop" window
* We let it be the size it wants, but it gets no decoration,
* is hidden in the toolbar and window cycling list, plus
* windows don't tab with it and is right on the bottom.
*/
setFocusHidden(true);
setIconHidden(true);
moveToLayer(::Layer::DESKTOP);
setDecorationMask(DECOR_NONE);
setTabable(false);
setMovable(false);
setResizable(false);
stick();
break;
case Focusable::TYPE_SPLASH:
/*
* _NET_WM_WINDOW_TYPE_SPLASH indicates that the
* window is a splash screen displayed as an application
* is starting up.
*/
setDecorationMask(DECOR_NONE);
setFocusHidden(true);
setIconHidden(true);
setMovable(false);
break;
case Focusable::TYPE_DIALOG:
setTabable(false);
break;
case Focusable::TYPE_MENU:
case Focusable::TYPE_TOOLBAR:
/*
* _NET_WM_WINDOW_TYPE_TOOLBAR and _NET_WM_WINDOW_TYPE_MENU
* indicate toolbar and pinnable menu windows, respectively
* (i.e. toolbars and menus "torn off" from the main
* application). Windows of this type may set the
* WM_TRANSIENT_FOR hint indicating the main application window.
*/
setDecorationMask(DECOR_TOOL);
setIconHidden(true);
moveToLayer(::Layer::ABOVE_DOCK);
break;
case Focusable::TYPE_NORMAL:
default:
break;
}
/*
* NOT YET IMPLEMENTED:
* _NET_WM_WINDOW_TYPE_UTILITY
*/
}

View file

@ -459,6 +459,8 @@ public:
const std::string &getWMClassName() const;
const std::string &getWMClassClass() const;
std::string getWMRole() const;
Focusable::WindowType getWindowType() const;
void setWindowType(Focusable::WindowType type);
bool isTransient() const;
inline int x() const { return frame().x(); }

View file

@ -301,9 +301,12 @@ void ShowDesktopCmd::execute() {
return;
Workspace::Windows windows(screen->currentWorkspace()->windowList());
std::for_each(windows.begin(),
windows.end(),
std::mem_fun(&FluxboxWindow::iconify));
Workspace::Windows::iterator it = windows.begin(),
it_end = windows.end();
for (; it != it_end; ++it) {
if ((*it)->getWindowType() != Focusable::TYPE_DESKTOP)
(*it)->iconify();
}
}
void CloseAllWindowsCmd::execute() {