#include "frame.hh"
#include "screen.hh"
#include "openbox.hh"
+#include "bindings.hh"
#include "otk/display.hh"
#include "otk/property.hh"
#define _(str) gettext(str)
}
+#include <algorithm>
+
namespace ob {
Client::Client(int screen, Window window)
_transient_for = 0;
// pick a layer to start from
_layer = Layer_Normal;
+ // default to not urgent
+ _urgent = false;
getArea();
getDesktop();
updateStrut();
// this makes sure that these windows appear on all desktops
- if (_type == Type_Dock || _type == Type_Desktop)
+ if (/*_type == Type_Dock ||*/ _type == Type_Desktop)
_desktop = 0xffffffff;
// set the desktop hint, to make sure that it always exists, and to reflect
// 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
+ }
}
_decorations |= Decor_Close;
_functions |= Func_Close;
}
+
+ if (_min_size.x() > _max_size.x() || _min_size.y() > _max_size.y()) {
+ _decorations &= ~Decor_Maximize;
+ _functions &= ~(Func_Resize | Func_Maximize);
+ }
switch (_type) {
case Type_Normal:
int oldgravity = _gravity;
// defaults
+ _min_ratio = 0.0;
+ _max_ratio = 0.0;
_size_inc.setPoint(1, 1);
_base_size.setPoint(0, 0);
_min_size.setPoint(0, 0);
}
}
+ if (size.flags & PAspect) {
+ if (size.min_aspect.y) _min_ratio = size.min_aspect.x/size.min_aspect.y;
+ if (size.max_aspect.y) _max_ratio = size.max_aspect.x/size.max_aspect.y;
+ }
+
if (size.flags & PMinSize)
_min_size.setPoint(size.min_width, size.min_height);
// 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 (frame)
+ fireUrgent();
+ }
}
_strut.left = data[0];
_strut.right = data[1];
_strut.top = data[2];
- _strut.bottom = data[3];
-
+ _strut.bottom = data[3];
+
openbox->screen(_screen)->updateStrut();
}
}
}
- if (e.atom == XA_WM_NORMAL_HINTS)
+ if (e.atom == XA_WM_NORMAL_HINTS) {
updateNormalHints();
- else if (e.atom == XA_WM_HINTS)
+ setupDecorAndFunctions(); // normal hints can make a window non-resizable
+ } else if (e.atom == XA_WM_HINTS)
updateWMHints();
else if (e.atom == XA_WM_TRANSIENT_FOR) {
updateTransientFor();
}
-void Client::internal_resize(Corner anchor, int w, int h, int x, int y)
+void Client::internal_resize(Corner anchor, int w, int h, bool user,
+ int x, int y)
{
w -= _base_size.x();
h -= _base_size.y();
w += _size_inc.x() / 2;
h += _size_inc.y() / 2;
- // is the window resizable? if it is not, then don't check its sizes, the
- // client can do what it wants and the user can't change it anyhow
- if (_min_size.x() <= _max_size.x() && _min_size.y() <= _max_size.y()) {
+ if (user) {
+ // if this is a user-requested resize, then check against min/max sizes
+ // and aspect ratios
+
// smaller than min size or bigger than max size?
if (w < _min_size.x()) w = _min_size.x();
else if (w > _max_size.x()) w = _max_size.x();
if (h < _min_size.y()) h = _min_size.y();
else if (h > _max_size.y()) h = _max_size.y();
+
+ // adjust the height ot match the width for the aspect ratios
+ if (_min_ratio)
+ if (h * _min_ratio > w) h = static_cast<int>(w / _min_ratio);
+ if (_max_ratio)
+ if (h * _max_ratio < w) h = static_cast<int>(w / _max_ratio);
}
// keep to the increments
// these are in a carefully crafted order..
if (_iconic) {
- printf("MAP ICONIC\n");
_iconic = false;
setDesktop(ICONIC_DESKTOP);
}
_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
XSendEvent(**otk::display, _window, False, NoEventMask, &ce);
}
+ XSync(**otk::display, False);
return true;
}
if (e.value_mask & (CWX | CWY)) {
int x = (e.value_mask & CWX) ? e.x : _area.x();
int y = (e.value_mask & CWY) ? e.y : _area.y();
- internal_resize(corner, w, h, x, y);
+ internal_resize(corner, w, h, false, x, y);
} else // if JUST resizing...
- internal_resize(corner, w, h);
+ internal_resize(corner, w, h, false);
} else if (e.value_mask & (CWX | CWY)) { // if JUST moving...
int x = (e.value_mask & CWX) ? e.x : _area.x();
int y = (e.value_mask & CWY) ? e.y : _area.y();
{
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;