Client.C
#include "Manager.h"
#include "Client.h"
#include <X11/Xutil.h>
#include <X11/keysym.h>
#if I18N
#include <X11/Xmu/Atoms.h>
10 #endif
const char *const Client::m_defaultLabel = "incognito";
Client::Client(WindowManager *const wm, Window w) :
m_window(w),
m_transient(None),
m_revert(0),
20 m_sticky(False),
m_fixedSize(False),
m_state(WithdrawnState),
m_managed(False),
m_reparenting(False),
m_stubborn(False),
m_lastPopTime(0L),
m_isFullHeight(False),
m_colormap(None),
m_colormapWinCount(0),
30 m_colormapWindows(NULL),
m_windowColormaps(NULL),
m_windowManager(wm)
{
XWindowAttributes attr;
XGetWindowAttributes(display(), m_window, &attr);
m_x = attr.x;
m_y = attr.y;
m_w = attr.width;
40 m_h = attr.height;
m_bw = attr.border_width;
m_name = m_iconName = 0;
m_sizeHints.flags = 0L;
m_label = NewString(m_defaultLabel);
m_border = new Border(this, w);
m_channel = wm->channel();
m_unmappedForChannel = False;
50
//#if CONFIG_MAD_FEEDBACK != 0
m_speculating = m_levelRaised = False;
//#endif
if (attr.map_state == IsViewable) manage(True);
}
Client::~Client()
60 {
// empty
}
void Client::release()
{
// assume wm called for this, and will remove me from its list itself
if (m_window == None) {
70 fprintf(stderr,
"wmx: invalid parent in Client::release (released twice?)\n");
}
windowManager()->skipInRevert(this, m_revert);
if (isHidden()) unhide(False);
windowManager()->removeFromOrderedList(this);
delete m_border;
80 m_window = None;
if (isActive()) {
if (CONFIG_CLICK_TO_FOCUS) {
if (m_revert) {
windowManager()->setActiveClient(m_revert);
m_revert->activate();
} else windowManager()->setActiveClient(0);
} else {
windowManager()->setActiveClient(0);
90 }
}
if (m_colormapWinCount > 0) {
XFree((char *)m_colormapWindows);
free((char *)m_windowColormaps); // not allocated through X
}
if (m_iconName) XFree(m_iconName);
if (m_name) XFree(m_name);
100 if (m_label) free((void *)m_label);
delete this;
}
void Client::unreparent()
{
XWindowChanges wc;
110 if (!isWithdrawn()) {
gravitate(True);
XReparentWindow(display(), m_window, root(), m_x, m_y);
}
wc.border_width = m_bw;
XConfigureWindow(display(), m_window, CWBorderWidth, &wc);
XSync(display(), True);
}
120
void Client::installColormap()
{
Client *cc = 0;
int i, found;
if (m_colormapWinCount != 0) {
found = 0;
130
for (i = m_colormapWinCount - 1; i >= 0; --i) {
windowManager()->installColormap(m_windowColormaps[i]);
if (m_colormapWindows[i] == m_window) ++found;
}
if (found == 0) {
windowManager()->installColormap(m_colormap);
}
140 } else if (m_transient != None &&
(cc = windowManager()->windowToClient(m_transient))) {
cc->installColormap();
} else {
windowManager()->installColormap(m_colormap);
}
}
150 void Client::manage(Boolean mapped)
{
static int lastX = 0, lastY = 0;
Boolean shouldHide, reshape;
XWMHints *hints;
Display *d = display();
long mSize;
int state;
XSelectInput(d, m_window, ColormapChangeMask | EnterWindowMask |
160 PropertyChangeMask | FocusChangeMask | KeyPressMask |
KeyReleaseMask); //!!!
if (CONFIG_USE_KEYBOARD) {
int i;
int keycode;
static KeySym keys[] = {
CONFIG_FLIP_UP_KEY, CONFIG_FLIP_DOWN_KEY, CONFIG_CIRCULATE_KEY,
170 CONFIG_HIDE_KEY, CONFIG_DESTROY_KEY, CONFIG_RAISE_KEY,
CONFIG_LOWER_KEY, CONFIG_FULLHEIGHT_KEY, CONFIG_NORMALHEIGHT_KEY,
CONFIG_STICKY_KEY
#if CONFIG_WANT_KEYBOARD_MENU
, CONFIG_MENU_KEY
#endif
};
for (i = 0; i < sizeof(keys)/sizeof(keys[0]); ++i) {
180 keycode = XKeysymToKeycode(display(), keys[i]);
if (keycode) {
XGrabKey(display(), keycode,
CONFIG_ALT_KEY_MASK, m_window, True,
GrabModeAsync, GrabModeAsync);
}
}
keycode = XKeysymToKeycode(display(), CONFIG_QUICKRAISE_KEY);
if (keycode) {
190 XGrabKey(display(), keycode, 0, m_window, True,
GrabModeAsync, GrabModeAsync);
}
keycode = XKeysymToKeycode(display(), CONFIG_QUICKHIDE_KEY);
if (keycode) {
XGrabKey(display(), keycode, 0, m_window, True,
GrabModeAsync, GrabModeAsync);
}
200 keycode = XKeysymToKeycode(display(), CONFIG_QUICKHEIGHT_KEY);
if (keycode) {
XGrabKey(display(), keycode, 0, m_window, True,
GrabModeAsync, GrabModeAsync);
}
if (CONFIG_USE_CHANNEL_KEYS) {
for (i = 0; i < 12; ++i) {
keycode = XKeysymToKeycode(display(), XK_F1 + i);
if (keycode) {
210 XGrabKey(display(), keycode,
CONFIG_ALT_KEY_MASK, m_window, True,
GrabModeAsync, GrabModeAsync);
}
}
}
}
m_iconName = getProperty(XA_WM_ICON_NAME);
m_name = getProperty(XA_WM_NAME);
220 setLabel();
getColormaps();
getProtocols();
getTransient();
hints = XGetWMHints(d, m_window);
#if CONFIG_USE_WINDOW_GROUPS != False
m_groupParent = hints ? hints->window_group : None;
230 if (m_groupParent == None) m_groupParent = m_window;
// fprintf(stderr, "Client %p (%s) has window %ld and groupParent %ld\n",
// this, m_name, m_window, m_groupParent);
#endif
if (!getState(&state)) {
state = hints ? hints->initial_state : NormalState;
}
shouldHide = (state == IconicState);
240 if (hints) XFree(hints);
if (XGetWMNormalHints(d, m_window, &m_sizeHints, &mSize) == 0 ||
m_sizeHints.flags == 0) {
m_sizeHints.flags = PSize;
}
m_fixedSize = False;
if ((m_sizeHints.flags & (PMinSize | PMaxSize)) == (PMinSize | PMaxSize) &&
(m_sizeHints.min_width == m_sizeHints.max_width &&
250 m_sizeHints.min_height == m_sizeHints.max_height)) m_fixedSize = True;
reshape = !mapped;
if (m_fixedSize) {
if ((m_sizeHints.flags & USPosition)) reshape = False;
if ((m_sizeHints.flags & PPosition) && shouldHide) reshape = False;
if ((m_transient != None)) reshape = False;
}
260 if ((m_sizeHints.flags & PBaseSize)) {
m_minWidth = m_sizeHints.base_width;
m_minHeight = m_sizeHints.base_height;
} else if ((m_sizeHints.flags & PMinSize)) {
m_minWidth = m_sizeHints.min_width;
m_minHeight = m_sizeHints.min_height;
} else {
m_minWidth = m_minHeight = 50;
}
270 // act
gravitate(False);
// zeros are iffy, should be calling some Manager method
int dw = DisplayWidth(display(), 0), dh = DisplayHeight(display(), 0);
if (m_w < m_minWidth) {
m_w = m_minWidth; m_fixedSize = False; reshape = True;
}
280 if (m_h < m_minHeight) {
m_h = m_minHeight; m_fixedSize = False; reshape = True;
}
if (m_w > dw - 8) m_w = dw - 8;
if (m_h > dh - 8) m_h = dh - 8;
if (!mapped && m_transient == None &&
!(m_sizeHints.flags & (PPosition | USPosition))) {
290 lastX += 60; lastY += 40;
if (lastX + m_w + m_border->xIndent() > dw) {
lastX = 0;
}
if (lastY + m_h + m_border->yIndent() > dh) {
lastY = 0;
}
m_x = lastX; m_y = lastY;
}
300
if (m_x > dw - m_border->xIndent()) {
m_x = dw - m_border->xIndent();
}
if (m_y > dh - m_border->yIndent()) {
m_y = dh - m_border->yIndent();
}
if (m_x < m_border->xIndent()) m_x = m_border->xIndent();
310 if (m_y < m_border->yIndent()) m_y = m_border->yIndent();
m_border->configure(m_x, m_y, m_w, m_h, 0L, Above);
if (mapped) m_reparenting = True;
if (reshape && !m_fixedSize) XResizeWindow(d, m_window, m_w, m_h);
XSetWindowBorderWidth(d, m_window, 0);
m_border->reparent();
320 // (support for shaped windows absent)
XAddToSaveSet(d, m_window);
m_managed = True;
if (shouldHide) hide();
else {
XMapWindow(d, m_window);
m_border->map();
setState(NormalState);
330
if (CONFIG_CLICK_TO_FOCUS ||
(m_transient != None && activeClient() &&
activeClient()->m_window == m_transient)) {
activate();
mapRaised();
} else {
deactivate();
}
}
340
if (activeClient() && !isActive()) {
activeClient()->installColormap();
}
if (CONFIG_AUTO_RAISE) {
m_windowManager->stopConsideringFocus();
focusIfAppropriate(False);
}
350 m_windowManager->hoistToTop(this);
sendConfigureNotify(); // due to Martin Andrews
}
void Client::selectOnMotion(Window w, Boolean select)
{
if (!CONFIG_AUTO_RAISE) return;
if (!w || w == root()) return;
360 if (w == m_window || m_border->hasWindow(w)) {
XSelectInput(display(), m_window, // not "w"
ColormapChangeMask | EnterWindowMask |
PropertyChangeMask | FocusChangeMask |
(select ? PointerMotionMask : 0L));
} else {
XSelectInput(display(), w, select ? PointerMotionMask : 0L);
}
}
370
void Client::decorate(Boolean active)
{
m_border->decorate(active, m_w, m_h);
}
void Client::activate()
{
// fprintf(stderr, "Client::activate (this = %p, window = %x, parent = %x)\n",
380 // this, m_window, parent());
if (parent() == root()) {
fprintf(stderr, "wmx: warning: bad parent in Client::activate\n");
return;
}
if (!m_managed || isHidden() || isWithdrawn() ||
(m_channel != windowManager()->channel())) return;
390 if (isActive()) {
decorate(True);
if (CONFIG_AUTO_RAISE || CONFIG_RAISE_ON_FOCUS) mapRaised();
return;
}
if (activeClient()) {
activeClient()->deactivate();
// & some other-screen business
}
400
XUngrabButton(display(), AnyButton, AnyModifier, parent());
XSetInputFocus(display(), m_window, RevertToPointerRoot,
windowManager()->timestamp(False));
if (m_protocol & PtakeFocus) {
sendMessage(Atoms::wm_protocols, Atoms::wm_takeFocus);
}
410 // now set revert of window that reverts to this one so as to
// revert to the window this one used to revert to (huh?)
windowManager()->skipInRevert(this, m_revert);
m_revert = activeClient();
while (m_revert && !m_revert->isNormal()) m_revert = m_revert->revertTo();
windowManager()->setActiveClient(this);
decorate(True);
420
installColormap(); // new!
}
void Client::deactivate() // called from wm?
{
if (parent() == root()) {
fprintf(stderr, "wmx: warning: bad parent in Client::deactivate\n");
return;
430 }
XGrabButton(display(), AnyButton, AnyModifier, parent(), False,
ButtonPressMask | ButtonReleaseMask,
GrabModeAsync, GrabModeSync, None, None);
decorate(False);
}
440 void Client::sendMessage(Atom a, long l)
{
XEvent ev;
int status;
long mask;
memset(&ev, 0, sizeof(ev));
ev.xclient.type = ClientMessage;
ev.xclient.window = m_window;
ev.xclient.message_type = a;
450 ev.xclient.format = 32;
ev.xclient.data.l[0] = l;
ev.xclient.data.l[1] = windowManager()->timestamp(False);
mask = 0L;
status = XSendEvent(display(), m_window, False, mask, &ev);
if (status == 0) {
fprintf(stderr, "wmx: warning: Client::sendMessage failed\n");
}
}
460
static int getProperty_aux(Display *d, Window w, Atom a, Atom type, long len,
unsigned char **p)
{
Atom realType;
int format;
unsigned long n, extra;
int status;
Boolean retried = False;
470
tryagain:
status = XGetWindowProperty(d, w, a, 0L, len, False, type, &realType,
&format, &n, &extra, p);
if (status != Success || *p == 0) return -1;
if (n == 0) XFree((void *) *p);
if (type == XA_STRING || type == AnyPropertyType || retried) {
if (realType != XA_STRING || format != 8) {
#if I18N
480 // XA_STRING is needed by a caller. But XGetWindowProperty()
// returns other typed data. So try to convert them.
XTextProperty textprop;
textprop.value = *p;
textprop.encoding = realType;
textprop.format = format;
textprop.nitems = n;
char **list;
int num, cnt;
490 cnt = XmbTextPropertyToTextList(d, &textprop, &list, &num);
unsigned char *string;
if (cnt == Success && num > 0 && *list) {
string = (unsigned char*)NewString(*list);
XFreeStringList(list);
n = num;
} else if (cnt > Success) {
fprintf(stderr, "Something wrong, cannot conver "
"text property\n"
" original type %ld, string %s\n"
500 " converted string %s\n"
" decide to use original value as STRING\n",
textprop.encoding, textprop.value, *list);
string = (unsigned char*)NewString(*(char**)p);
XFreeStringList(list);
n = n;
} else if (!retried) {
retried = True;
type = AnyPropertyType;
goto tryagain;
510 } else {
string = NULL;
n = 0;
}
XFree((void *) *p);
*p = string;
#else
XFree((void *) *p);
*p = NULL;
#endif
520 }
}
return n;
}
char *Client::getProperty(Atom a)
{
unsigned char *p;
530
// no -- allow any type, not just string -- SGI has "compound
// text", and part-garbage is possibly better than "incognito" --
// thanks to Bill Spitzak
// if (getProperty_aux(display(), m_window, a, XA_STRING, 100L, &p) <= 0) {
if (getProperty_aux(display(), m_window, a, AnyPropertyType, 100L, &p) <= 0) {
return NULL;
}
return (char *)p;
540 }
int Client::getAtomProperty(Atom a, Atom type)
{
char **p, *x;
if (getProperty_aux(display(), m_window, a, type, 1L,
(unsigned char **)&p) <= 0) {
return 0;
}
550
x = *p;
XFree((void *)p);
return (int)x;
}
int Client::getIntegerProperty(Atom a)
{
return getAtomProperty(a, XA_INTEGER);
560 }
void Client::setState(int state)
{
m_state = state;
long data[2];
data[0] = (long)state;
data[1] = (long)None;
570
XChangeProperty(display(), m_window, Atoms::wm_state, Atoms::wm_state,
32, PropModeReplace, (unsigned char *)data, 2);
}
Boolean Client::getState(int *state)
{
long *p = 0;
580 if (getProperty_aux(display(), m_window, Atoms::wm_state, Atoms::wm_state,
2L, (unsigned char **)&p) <= 0) {
return False;
}
*state = (int) *p;
XFree((char *)p);
return True;
}
590
void Client::getProtocols()
{
long n;
Atom *p;
m_protocol = 0;
if ((n = getProperty_aux(display(), m_window, Atoms::wm_protocols, XA_ATOM,
20L, (unsigned char **)&p)) <= 0) {
return;
600 }
for (int i = 0; i < n; ++i) {
if (p[i] == Atoms::wm_delete) {
m_protocol |= Pdelete;
} else if (p[i] == Atoms::wm_takeFocus) {
m_protocol |= PtakeFocus;
}
}
610 XFree((char *) p);
}
void Client::gravitate(Boolean invert)
{
int gravity;
int w = 0, h = 0, xdelta, ydelta;
// possibly shouldn't work if we haven't been managed yet?
620
gravity = NorthWestGravity;
if (m_sizeHints.flags & PWinGravity) gravity = m_sizeHints.win_gravity;
xdelta = m_bw - m_border->xIndent();
ydelta = m_bw - m_border->yIndent();
// note that right and bottom borders have indents of 1
switch (gravity) {
630
case NorthWestGravity:
break;
case NorthGravity:
w = xdelta;
break;
case NorthEastGravity:
w = xdelta + m_bw-1;
640 break;
case WestGravity:
h = ydelta;
break;
case CenterGravity:
case StaticGravity:
w = xdelta;
h = ydelta;
650 break;
case EastGravity:
w = xdelta + m_bw-1;
h = ydelta;
break;
case SouthWestGravity:
h = ydelta + m_bw-1;
break;
660
case SouthGravity:
w = xdelta;
h = ydelta + m_bw-1;
break;
case SouthEastGravity:
w = xdelta + m_bw-1;
h = ydelta + m_bw-1;
break;
670
default:
fprintf(stderr, "wmx: bad window gravity %d for window 0x%lx\n",
gravity, m_window);
return;
}
w += m_border->xIndent();
h += m_border->yIndent();
680 if (invert) { w = -w; h = -h; }
m_x += w;
m_y += h;
}
Boolean Client::setLabel(void)
{
const char *newLabel;
690
if (m_name) newLabel = m_name;
else if (m_iconName) newLabel = m_iconName;
else newLabel = m_defaultLabel;
if (!m_label) {
m_label = NewString(newLabel);
return True;
700 } else if (strcmp(m_label, newLabel)) {
free((void *)m_label);
m_label = NewString(newLabel);
return True;
} else return True;//False;// dammit!
}
710 void Client::getColormaps(void)
{
int i, n;
Window *cw;
XWindowAttributes attr;
if (!m_managed) {
XGetWindowAttributes(display(), m_window, &attr);
m_colormap = attr.colormap;
}
720
n = getProperty_aux(display(), m_window, Atoms::wm_colormaps, XA_WINDOW,
100L, (unsigned char **)&cw);
if (m_colormapWinCount != 0) {
XFree((char *)m_colormapWindows);
free((char *)m_windowColormaps);
}
if (n <= 0) {
730 m_colormapWinCount = 0;
return;
}
m_colormapWinCount = n;
m_colormapWindows = cw;
m_windowColormaps = (Colormap *)malloc(n * sizeof(Colormap));
for (i = 0; i < n; ++i) {
740 if (cw[i] == m_window) {
m_windowColormaps[i] = m_colormap;
} else {
XSelectInput(display(), cw[i], ColormapChangeMask);
XGetWindowAttributes(display(), cw[i], &attr);
m_windowColormaps[i] = attr.colormap;
}
}
}
750
void Client::getTransient()
{
Window t = None;
if (XGetTransientForHint(display(), m_window, &t) != 0) {
if (windowManager()->windowToClient(t) == this) {
fprintf(stderr,
"wmx: warning: client \"%s\" thinks it's a transient "
760 "for\nitself -- ignoring WM_TRANSIENT_FOR property...\n",
m_label ? m_label : "(no name)");
m_transient = None;
} else {
m_transient = t;
}
} else {
m_transient = None;
}
}
770
void Client::hide()
{
if (isHidden()) {
fprintf(stderr, "wmx: Client already hidden in Client::hide\n");
return;
}
m_border->unmap();
780 XUnmapWindow(display(), m_window);
if (isActive()) windowManager()->clearFocus();
setState(IconicState);
windowManager()->addToHiddenList(this);
#if CONFIG_USE_WINDOW_GROUPS != False
if (isGroupParent()) {
windowManager()->hideGroup(groupParent(), this);
790 }
#endif
}
void Client::unhide(Boolean map)
{
if (CONFIG_MAD_FEEDBACK) {
m_speculating = False;
if (!isHidden()) return;
800 }
if (!isHidden()) {
fprintf(stderr, "wmx: Client not hidden in Client::unhide\n");
return;
}
windowManager()->removeFromHiddenList(this);
if (map) {
810 setState(NormalState);
if (m_channel == windowManager()->channel()) {
XMapWindow(display(), m_window);
}
mapRaised();
if (CONFIG_AUTO_RAISE) focusIfAppropriate(False);
else if (CONFIG_CLICK_TO_FOCUS) activate();
}
820
#if CONFIG_USE_WINDOW_GROUPS != False
if (isGroupParent()) {
windowManager()->unhideGroup(groupParent(), this, map);
}
#endif
}
void Client::sendConfigureNotify()
830 {
XConfigureEvent ce;
ce.type = ConfigureNotify;
ce.event = m_window;
ce.window = m_window;
ce.x = m_x;
ce.y = m_y;
ce.width = m_w;
840 ce.height = m_h;
ce.border_width = m_bw;
ce.above = None;
ce.override_redirect = 0;
XSendEvent(display(), m_window, False, StructureNotifyMask, (XEvent*)&ce);
}
void Client::withdraw(Boolean changeState)
850 {
m_border->unmap();
gravitate(True);
XReparentWindow(display(), m_window, root(), m_x, m_y);
gravitate(False);
if (changeState) {
XRemoveFromSaveSet(display(), m_window);
860 setState(WithdrawnState);
}
#if CONFIG_USE_WINDOW_GROUPS != False
if (isGroupParent()) {
windowManager()->withdrawGroup(groupParent(), this, changeState);
}
#endif
ignoreBadWindowErrors = True;
870 XSync(display(), False);
ignoreBadWindowErrors = False;
}
void Client::rename()
{
m_border->configure(0, 0, m_w, m_h, CWWidth | CWHeight, Above);
}
880
void Client::mapRaised()
{
if (m_channel == windowManager()->channel()) m_border->mapRaised();
windowManager()->hoistToTop(this);
windowManager()->raiseTransients(this);
}
void Client::kill()
890 {
if (m_protocol & Pdelete) {
sendMessage(Atoms::wm_protocols, Atoms::wm_delete);
} else {
XKillClient(display(), m_window);
}
#if CONFIG_USE_WINDOW_GROUPS != False
if (isGroupParent()) {
windowManager()->killGroup(groupParent(), this);
900 }
#endif
}
void Client::ensureVisible()
{
int mx = DisplayWidth(display(), 0) - 1; // hack
int my = DisplayHeight(display(), 0) - 1;
int px = m_x;
910 int py = m_y;
if (m_x + m_w > mx) m_x = mx - m_w;
if (m_y + m_h > my) m_y = my - m_h;
if (m_x < 0) m_x = 0;
if (m_y < 0) m_y = 0;
if (m_x != px || m_y != py) {
m_border->moveTo(m_x, m_y);
sendConfigureNotify();
920 }
}
void Client::lower()
{
m_border->lower();
windowManager()->hoistToBottom(this);
}
930
void Client::raiseOrLower()
{
if (windowManager()->isTop(this)) {
lower();
} else {
mapRaised();
}
}
940
void Client::fullHeight()
{
if (m_isFullHeight || m_fixedSize || (m_transient != None)) return;
m_normalH = m_h;
m_normalY = m_y;
m_h = DisplayHeight(display(), windowManager()->screen())
- m_border->yIndent() - 1;
950 int dw, dh;
fixResizeDimensions(m_w, m_h, dw, dh);
if (m_h > m_normalH) {
m_y -= (m_h - m_normalH);
if (m_y < m_border->yIndent()) m_y = m_border->yIndent();
}
m_isFullHeight = True;
960 m_border->configure(m_x, m_y, m_w, m_h, CWY | CWHeight, 0);
XResizeWindow(display(), m_window, m_w, m_h);
sendConfigureNotify();
}
void Client::normalHeight()
{
if (!m_isFullHeight) return;
970 m_h = m_normalH;
m_y = m_normalY;
m_isFullHeight = False;
m_border->configure(m_x, m_y, m_w, m_h, CWY | CWHeight, 0);
XResizeWindow(display(), m_window, m_w, m_h);
sendConfigureNotify();
}
980 void Client::warpPointer()
{
XWarpPointer(display(), None, parent(), 0, 0, 0, 0,
m_border->xIndent() / 2, m_border->xIndent() + 8);
}
void Client::flipChannel(Boolean leaving, int newChannel)
{
// fprintf(stderr, "I could be supposed to pop up now...\n");
990
if (m_channel != windowManager()->channel()) {
if (CONFIG_MAD_FEEDBACK) {
if (leaving && m_channel == newChannel &&
m_unmappedForChannel) {
showFeedback();
}
}
1000 return;
}
if (leaving) {
if (CONFIG_MAD_FEEDBACK) {
removeFeedback(isNormal()); // mostly it won't be there anyway, but...
}
if (!isNormal()) return;
1010 m_unmappedForChannel = True;
XUnmapWindow(display(), m_window);
withdraw(False);
return;
} else {
if (CONFIG_MAD_FEEDBACK) {
removeFeedback(isNormal()); // likewise
}
1020
if (!m_unmappedForChannel) {
if (isNormal()) mapRaised();
return;
}
m_unmappedForChannel = False;
setState(WithdrawnState);
m_border->reparent();
1030 if (CONFIG_AUTO_RAISE) m_windowManager->stopConsideringFocus();
XAddToSaveSet(display(), m_window);
XMapWindow(display(), m_window);
setState(NormalState);
mapRaised();
if (CONFIG_CLICK_TO_FOCUS) activate();
}
}
1040 void Client::showFeedback()
{
if (CONFIG_MAD_FEEDBACK) {
if (m_speculating || m_levelRaised) removeFeedback(False);
m_border->showFeedback(m_x, m_y, m_w, m_h);
// XSync(display(), False);
}
}
void Client::raiseFeedbackLevel()
1050 {
if (CONFIG_MAD_FEEDBACK) {
m_border->removeFeedback();
m_levelRaised = True;
if (isNormal()) {
mapRaised();
} else if (isHidden()) {
unhide(True);
1060 m_speculating = True;
// XSync(display(), False);
}
}
}
void Client::removeFeedback(Boolean mapped)
{
if (CONFIG_MAD_FEEDBACK) {
1070 m_border->removeFeedback();
if (m_levelRaised) {
if (m_speculating) {
if (!mapped) hide();
XSync(display(), False);
} else {
// not much we can do
}
}
1080
m_speculating = m_levelRaised = False;
}
}