#include "frame.hh"
#include "screen.hh"
#include "openbox.hh"
+#include "bindings.hh"
#include "otk/display.hh"
#include "otk/property.hh"
// update EVERYTHING the first time!!
// we default to NormalState, visible
- _wmstate = NormalState; _iconic = false;
- // no default decors or functions, each has to be enabled
- _decorations = _functions = 0;
+ _wmstate = NormalState;
// start unfocused
_focused = false;
// not a transient by default of course
_transient_for = 0;
// pick a layer to start from
_layer = Layer_Normal;
+ // default to not urgent
+ _urgent = false;
getArea();
getDesktop();
getType();
getMwmHints();
- getState(); // gets all the states except for iconic, which is found from
- // the desktop == ICONIC_DESKTOP
+ getState();
getShaped();
updateProtocols();
getGravity(); // get the attribute gravity
updateNormalHints(); // this may override the attribute gravity
- updateWMHints(true); // also get the initial_state and set _iconic
+ // also get the initial_state and set _iconic if we aren't "starting"
+ // when we're "starting" that means we should use whatever state was already
+ // on the window over the initial map state, because it was already mapped
+ updateWMHints(openbox->state() != Openbox::State_Starting);
updateTitle();
updateIconTitle();
updateClass();
updateStrut();
- // this makes sure that these windows:
- // a) appear on all desktops
- // b) don't start iconified
- if (_type == Type_Dock || _type == Type_Desktop) {
+ // this makes sure that these windows appear on all desktops
+ if (/*_type == Type_Dock ||*/ _type == Type_Desktop)
_desktop = 0xffffffff;
- }
- // restores iconic state when we restart.
- // this will override the initial_state if that was set
- if (_desktop == ICONIC_DESKTOP) _iconic = true;
-
// set the desktop hint, to make sure that it always exists, and to reflect
// any changes we've made here
otk::Property::set(_window, otk::Property::atoms.net_wm_desktop,
// defaults to the current desktop
_desktop = openbox->screen(_screen)->desktop();
- otk::Property::get(_window, otk::Property::atoms.net_wm_desktop,
- otk::Property::atoms.cardinal,
- (long unsigned*)&_desktop);
+ if (otk::Property::get(_window, otk::Property::atoms.net_wm_desktop,
+ otk::Property::atoms.cardinal,
+ (long unsigned*)&_desktop)) {
+#ifdef DEBUG
+// printf("Window requested desktop: %ld\n", _desktop);
+#endif
+ }
}
void Client::getState()
{
_modal = _shaded = _max_horz = _max_vert = _fullscreen = _above = _below =
- _skip_taskbar = _skip_pager = false;
+ _iconic = _skip_taskbar = _skip_pager = false;
unsigned long *state;
unsigned long num = (unsigned) -1;
_modal = true;
else if (state[i] == otk::Property::atoms.net_wm_state_shaded)
_shaded = true;
+ else if (state[i] == otk::Property::atoms.net_wm_state_hidden)
+ _iconic = true;
else if (state[i] == otk::Property::atoms.net_wm_state_skip_taskbar)
_skip_taskbar = true;
else if (state[i] == otk::Property::atoms.net_wm_state_skip_pager)
// assume a window takes input if it doesnt specify
_can_focus = true;
- _urgent = false;
+ bool ur = false;
if ((hints = XGetWMHints(**otk::display, _window)) != NULL) {
if (hints->flags & InputHint)
_iconic = hints->initial_state == IconicState;
if (hints->flags & XUrgencyHint)
- _urgent = true;
+ ur = true;
if (hints->flags & WindowGroupHint) {
if (hints->window_group != _group) {
XFree(hints);
}
+
+ if (ur != _urgent) {
+ _urgent = ur;
+#ifdef DEBUG
+ printf("DEBUG: Urgent Hint for 0x%lx: %s\n",
+ (long)_window, _urgent ? "ON" : "OFF");
+#endif
+ // fire the urgent callback if we're mapped, otherwise, wait until after
+ // we're mapped
+ if (_urgent && frame)
+ fireUrgent();
+ }
}
_desktop = target;
- // set the desktop hint
- otk::Property::set(_window, otk::Property::atoms.net_wm_desktop,
- otk::Property::atoms.cardinal, (unsigned)_desktop);
+ // set the desktop hint, but not if we're iconifying
+ if (_desktop != ICONIC_DESKTOP)
+ otk::Property::set(_window, otk::Property::atoms.net_wm_desktop,
+ otk::Property::atoms.cardinal, (unsigned)_desktop);
// 'move' the window to the new desktop
if (_desktop == openbox->screen(_screen)->desktop() ||
if (_iconic) {
_iconic = false;
- _desktop = 0; // set some other source desktop so this goes through
setDesktop(ICONIC_DESKTOP);
}
if (_fullscreen) {
_shaded = false;
shade(true);
}
+ if (_urgent)
+ fireUrgent();
if (_max_vert); // XXX: incomplete
if (_max_horz); // XXX: incomplete
}
+void Client::fireUrgent()
+{
+ // call the python UrgentWindow callbacks
+ EventData data(_screen, this, EventAction::UrgentWindow, 0);
+ openbox->bindings()->fireEvent(&data);
+}
+
+
void Client::shade(bool shade)
{
if (!(_functions & Func_Shade) || // can't
}
-bool Client::focus() const
+bool Client::focus()
{
// won't try focus if the client doesn't want it, or if the window isn't
// visible on the screen
if (_focused) return true;
// do a check to see if the window has already been unmapped or destroyed
+ // do this intelligently while watching out for unmaps we've generated
+ // (ignore_unmaps > 0)
XEvent ev;
- if (XCheckTypedWindowEvent(**otk::display, _window, UnmapNotify, &ev) ||
- XCheckTypedWindowEvent(**otk::display, _window, DestroyNotify, &ev)) {
+ if (XCheckTypedWindowEvent(**otk::display, _window, DestroyNotify, &ev)) {
XPutBackEvent(**otk::display, &ev);
return false;
}
+ while (XCheckTypedWindowEvent(**otk::display, _window, UnmapNotify, &ev)) {
+ if (ignore_unmaps) {
+ unmapHandler(ev.xunmap);
+ } else {
+ XPutBackEvent(**otk::display, &ev);
+ return false;
+ }
+ }
if (_can_focus)
XSetInputFocus(**otk::display, _window,
{
if (ignore_unmaps) {
#ifdef DEBUG
- printf("Ignored UnmapNotify for 0x%lx (event 0x%lx)\n", e.window, e.event);
+// printf("Ignored UnmapNotify for 0x%lx (event 0x%lx)\n", e.window, e.event);
#endif // DEBUG
ignore_unmaps--;
return;