742 lines
17 KiB
C++
742 lines
17 KiB
C++
|
|
||
|
#include "Manager.h"
|
||
|
#include "Client.h"
|
||
|
#include <sys/time.h>
|
||
|
|
||
|
#define AllButtonMask ( Button1Mask | Button2Mask | Button3Mask \
|
||
|
| Button4Mask | Button5Mask )
|
||
|
#define ButtonMask ( ButtonPressMask | ButtonReleaseMask )
|
||
|
#define DragMask ( ButtonMask | ButtonMotionMask )
|
||
|
#define MenuMask ( ButtonMask | ButtonMotionMask | ExposureMask )
|
||
|
#define MenuGrabMask ( ButtonMask | ButtonMotionMask | StructureNotifyMask )
|
||
|
|
||
|
|
||
|
void WindowManager::eventButton(XButtonEvent *e)
|
||
|
{
|
||
|
if (e->button == Button3) {
|
||
|
circulate(e->window == e->root);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
Client *c = windowToClient(e->window);
|
||
|
|
||
|
if (e->window == e->root) {
|
||
|
|
||
|
if (e->button == Button1) menu(e);
|
||
|
|
||
|
} else if (c) {
|
||
|
|
||
|
c->eventButton(e);
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
void WindowManager::circulate(Boolean activeFirst)
|
||
|
{
|
||
|
Client *c = 0;
|
||
|
if (activeFirst) c = m_activeClient;
|
||
|
|
||
|
if (!c) {
|
||
|
|
||
|
int i, j;
|
||
|
|
||
|
if (!m_activeClient) i = -1;
|
||
|
else {
|
||
|
for (i = 0; i < m_clients.count(); ++i) {
|
||
|
if (m_clients.item(i) == m_activeClient) break;
|
||
|
}
|
||
|
|
||
|
if (i >= m_clients.count()-1) i = -1;
|
||
|
}
|
||
|
|
||
|
for (j = i + 1;
|
||
|
(!m_clients.item(j)->isNormal() ||
|
||
|
m_clients.item(j)->isTransient()); ++j) {
|
||
|
if (j >= m_clients.count() - 1) j = -1;
|
||
|
if (j == i) return; // no suitable clients
|
||
|
}
|
||
|
|
||
|
c = m_clients.item(j);
|
||
|
}
|
||
|
|
||
|
c->activateAndWarp();
|
||
|
}
|
||
|
|
||
|
|
||
|
void Client::activateAndWarp()
|
||
|
{
|
||
|
mapRaised();
|
||
|
ensureVisible();
|
||
|
XWarpPointer(display(), None, parent(), 0, 0, 0, 0,
|
||
|
m_border->xIndent() / 2, m_border->xIndent() + 8);
|
||
|
activate();
|
||
|
}
|
||
|
|
||
|
|
||
|
void Client::eventButton(XButtonEvent *e)
|
||
|
{
|
||
|
if (e->type != ButtonPress) return;
|
||
|
|
||
|
mapRaised();
|
||
|
|
||
|
if (e->button == Button1) {
|
||
|
if (m_border->hasWindow(e->window)) {
|
||
|
|
||
|
m_border->eventButton(e);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!isNormal() || isActive() || e->send_event) return;
|
||
|
activate();
|
||
|
}
|
||
|
|
||
|
|
||
|
static int nobuttons(XButtonEvent *e) // straight outta 9wm
|
||
|
{
|
||
|
int state;
|
||
|
state = (e->state & AllButtonMask);
|
||
|
return (e->type == ButtonRelease) && (state & (state - 1)) == 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
int WindowManager::attemptGrab(Window w, Window constrain, int mask, int t)
|
||
|
{
|
||
|
int status;
|
||
|
if (t == 0) t = timestamp(False);
|
||
|
status = XGrabPointer(display(), w, False, mask, GrabModeAsync,
|
||
|
GrabModeAsync, constrain, None, t);
|
||
|
return status;
|
||
|
}
|
||
|
|
||
|
|
||
|
void WindowManager::releaseGrab(XButtonEvent *e)
|
||
|
{
|
||
|
XEvent ev;
|
||
|
if (!nobuttons(e)) {
|
||
|
for (;;) {
|
||
|
XMaskEvent(display(), ButtonMask | ButtonMotionMask, &ev);
|
||
|
if (ev.type == MotionNotify) continue;
|
||
|
e = &ev.xbutton;
|
||
|
if (nobuttons(e)) break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
XUngrabPointer(display(), e->time);
|
||
|
m_currentTime = e->time;
|
||
|
}
|
||
|
|
||
|
|
||
|
void WindowManager::menu(XButtonEvent *e)
|
||
|
{
|
||
|
if (e->window == m_menuWindow) return;
|
||
|
|
||
|
int i;
|
||
|
ClientList clients;
|
||
|
Boolean allowExit = False;
|
||
|
|
||
|
#define MENU_LABEL(n) ((n)==0 ? m_menuCreateLabel : \
|
||
|
(allowExit && ((n) > clients.count())) ? "[Exit wm2]" \
|
||
|
: clients.item((n)-1)->label())
|
||
|
|
||
|
for (i = 0; i < m_hiddenClients.count(); ++i) {
|
||
|
clients.append(m_hiddenClients.item(i));
|
||
|
}
|
||
|
int nh = clients.count() + 1;
|
||
|
|
||
|
if (CONFIG_EVERYTHING_ON_ROOT_MENU) {
|
||
|
for (i = 0; i < m_clients.count(); ++i) {
|
||
|
if (m_clients.item(i)->isNormal()) {
|
||
|
clients.append(m_clients.item(i));
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
int n = clients.count() + 1;
|
||
|
|
||
|
int mx = DisplayWidth (display(), m_screenNumber) - 1;
|
||
|
int my = DisplayHeight(display(), m_screenNumber) - 1;
|
||
|
|
||
|
allowExit = ((e->x > mx-3) && (e->y > my-3));
|
||
|
if (allowExit) n += 1;
|
||
|
|
||
|
int width, maxWidth = 10;
|
||
|
for (i = 0; i < n; ++i) {
|
||
|
width = XTextWidth(m_menuFont, MENU_LABEL(i), strlen(MENU_LABEL(i)));
|
||
|
if (width > maxWidth) maxWidth = width;
|
||
|
}
|
||
|
maxWidth += 32;
|
||
|
|
||
|
int selecting = -1, prev = -1;
|
||
|
int entryHeight = m_menuFont->ascent + m_menuFont->descent + 4;
|
||
|
int totalHeight = entryHeight * n + 13;
|
||
|
int x = e->x - maxWidth/2;
|
||
|
int y = e->y - 2;
|
||
|
Boolean warp = False;
|
||
|
|
||
|
if (x < 0) {
|
||
|
e->x -= x; x = 0; warp = True;
|
||
|
} else if (x + maxWidth >= mx) {
|
||
|
e->x -= x + maxWidth - mx; x = mx - maxWidth; warp = True;
|
||
|
}
|
||
|
|
||
|
if (y < 0) {
|
||
|
e->y -= y; y = 0; warp = True;
|
||
|
} else if (y + totalHeight >= my) {
|
||
|
e->y -= y + totalHeight - my; y = my - totalHeight; warp = True;
|
||
|
}
|
||
|
|
||
|
if (warp) XWarpPointer(display(), None, root(),
|
||
|
None, None, None, None, e->x, e->y);
|
||
|
|
||
|
XMoveResizeWindow(display(), m_menuWindow, x, y, maxWidth, totalHeight);
|
||
|
XSelectInput(display(), m_menuWindow, MenuMask);
|
||
|
XMapRaised(display(), m_menuWindow);
|
||
|
|
||
|
if (attemptGrab(m_menuWindow, None, MenuGrabMask, e->time) != GrabSuccess){
|
||
|
XUnmapWindow(display(), m_menuWindow);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
Boolean done = False;
|
||
|
Boolean drawn = False;
|
||
|
XEvent event;
|
||
|
|
||
|
while (!done) {
|
||
|
XMaskEvent(display(), MenuMask, &event);
|
||
|
|
||
|
switch (event.type) {
|
||
|
|
||
|
default:
|
||
|
fprintf(stderr, "wm2: unknown event type %d\n", event.type);
|
||
|
break;
|
||
|
|
||
|
case ButtonPress:
|
||
|
break;
|
||
|
|
||
|
case ButtonRelease:
|
||
|
if (drawn) {
|
||
|
|
||
|
if (event.xbutton.button != e->button) break;
|
||
|
x = event.xbutton.x;
|
||
|
y = event.xbutton.y - 11;
|
||
|
i = y / entryHeight;
|
||
|
|
||
|
if (selecting >= 0 && y >= selecting * entryHeight - 3 &&
|
||
|
y <= (selecting+1) * entryHeight - 3) i = selecting;
|
||
|
|
||
|
if (x < 0 || x > maxWidth || y < -3) i = -1;
|
||
|
else if (i < 0 || i >= n) i = -1;
|
||
|
|
||
|
} else {
|
||
|
selecting = -1;
|
||
|
}
|
||
|
|
||
|
if (!nobuttons(&event.xbutton)) i = -1;
|
||
|
releaseGrab(&event.xbutton);
|
||
|
XUnmapWindow(display(), m_menuWindow);
|
||
|
selecting = i;
|
||
|
done = True;
|
||
|
break;
|
||
|
|
||
|
case MotionNotify:
|
||
|
if (!drawn) break;
|
||
|
x = event.xbutton.x;
|
||
|
y = event.xbutton.y - 11;
|
||
|
prev = selecting;
|
||
|
selecting = y / entryHeight;
|
||
|
|
||
|
if (prev >= 0 && y >= prev * entryHeight - 3 &&
|
||
|
y <= (prev+1) * entryHeight - 3) selecting = prev;
|
||
|
|
||
|
if (x < 0 || x > maxWidth || y < -3) selecting = -1;
|
||
|
else if (selecting < 0 || selecting > n) selecting = -1;
|
||
|
|
||
|
if (selecting == prev) break;
|
||
|
|
||
|
if (prev >= 0 && prev < n) {
|
||
|
XFillRectangle(display(), m_menuWindow, m_menuGC,
|
||
|
4, prev * entryHeight + 9,
|
||
|
maxWidth - 8, entryHeight);
|
||
|
}
|
||
|
|
||
|
if (selecting >= 0 && selecting < n) {
|
||
|
XFillRectangle(display(), m_menuWindow, m_menuGC,
|
||
|
4, selecting * entryHeight + 9,
|
||
|
maxWidth - 8, entryHeight);
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
|
||
|
case Expose:
|
||
|
XClearWindow(display(), m_menuWindow);
|
||
|
|
||
|
XDrawRectangle(display(), m_menuWindow, m_menuGC, 2, 7,
|
||
|
maxWidth - 5, totalHeight - 10);
|
||
|
|
||
|
for (i = 0; i < n; ++i) {
|
||
|
|
||
|
int dx = XTextWidth(m_menuFont, MENU_LABEL(i),
|
||
|
strlen(MENU_LABEL(i)));
|
||
|
int dy = i * entryHeight + m_menuFont->ascent + 10;
|
||
|
|
||
|
if (i >= nh) {
|
||
|
XDrawString(display(), m_menuWindow, m_menuGC,
|
||
|
maxWidth - 8 - dx, dy,
|
||
|
MENU_LABEL(i), strlen(MENU_LABEL(i)));
|
||
|
} else {
|
||
|
XDrawString(display(), m_menuWindow, m_menuGC, 8,
|
||
|
dy, MENU_LABEL(i), strlen(MENU_LABEL(i)));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (selecting >= 0 && selecting < n) {
|
||
|
XFillRectangle(display(), m_menuWindow, m_menuGC,
|
||
|
4, selecting * entryHeight + 9,
|
||
|
maxWidth - 8, entryHeight);
|
||
|
}
|
||
|
|
||
|
drawn = True;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (selecting == n-1 && allowExit) {
|
||
|
m_signalled = True;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (selecting >= 0) {
|
||
|
if (selecting == 0) {
|
||
|
spawn();
|
||
|
} else if (selecting < nh) {
|
||
|
clients.item(selecting - 1)->unhide(True);
|
||
|
} else if (selecting < n) {
|
||
|
if (CONFIG_CLICK_TO_FOCUS) {
|
||
|
clients.item(selecting - 1)->activate();
|
||
|
} else {
|
||
|
clients.item(selecting - 1)->mapRaised();
|
||
|
}
|
||
|
clients.item(selecting - 1)->ensureVisible();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
clients.remove_all();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
|
||
|
void WindowManager::showGeometry(int x, int y)
|
||
|
{
|
||
|
char string[20];
|
||
|
snprintf(string, sizeof(string), "%d %d\n", x, y);
|
||
|
int width = XTextWidth(m_menuFont, string, strlen(string)) + 8;
|
||
|
int height = m_menuFont->ascent + m_menuFont->descent + 8;
|
||
|
int mx = DisplayWidth (display(), m_screenNumber) - 1;
|
||
|
int my = DisplayHeight(display(), m_screenNumber) - 1;
|
||
|
|
||
|
XMoveResizeWindow(display(), m_menuWindow,
|
||
|
(mx - width) / 2, (my - height) / 2, width, height);
|
||
|
XClearWindow(display(), m_menuWindow);
|
||
|
XMapRaised(display(), m_menuWindow);
|
||
|
|
||
|
XDrawString(display(), m_menuWindow, m_menuGC, 4, 4 + m_menuFont->ascent,
|
||
|
string, strlen(string));
|
||
|
}
|
||
|
|
||
|
|
||
|
void WindowManager::removeGeometry()
|
||
|
{
|
||
|
XUnmapWindow(display(), m_menuWindow);
|
||
|
}
|
||
|
|
||
|
|
||
|
void Client::move(XButtonEvent *e)
|
||
|
{
|
||
|
int x = -1, y = -1, xoff, yoff;
|
||
|
Boolean done = False;
|
||
|
|
||
|
if (m_windowManager->attemptGrab
|
||
|
(root(), None, DragMask, e->time) != GrabSuccess) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
xoff = m_border->xIndent() - e->x;
|
||
|
yoff = m_border->yIndent() - e->y;
|
||
|
|
||
|
XEvent event;
|
||
|
Boolean found;
|
||
|
Boolean doSomething = False;
|
||
|
struct timeval sleepval;
|
||
|
|
||
|
while (!done) {
|
||
|
|
||
|
found = False;
|
||
|
|
||
|
while (XCheckMaskEvent(display(), DragMask | ExposureMask, &event)) {
|
||
|
found = True;
|
||
|
if (event.type != MotionNotify) break;
|
||
|
}
|
||
|
|
||
|
if (!found) {
|
||
|
sleepval.tv_sec = 0;
|
||
|
sleepval.tv_usec = 50000;
|
||
|
select(0, 0, 0, 0, &sleepval);
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
switch (event.type) {
|
||
|
|
||
|
default:
|
||
|
fprintf(stderr, "wm2: unknown event type %d\n", event.type);
|
||
|
break;
|
||
|
|
||
|
case Expose:
|
||
|
m_windowManager->eventExposure(&event.xexpose);
|
||
|
break;
|
||
|
|
||
|
case ButtonPress:
|
||
|
// don't like this
|
||
|
XUngrabPointer(display(), event.xbutton.time);
|
||
|
doSomething = False;
|
||
|
done = True;
|
||
|
break;
|
||
|
|
||
|
case ButtonRelease:
|
||
|
|
||
|
x = event.xbutton.x; y = event.xbutton.y;
|
||
|
if (!nobuttons(&event.xbutton)) doSomething = False;
|
||
|
|
||
|
// XUngrabPointer(display(), event.xbutton.time);
|
||
|
m_windowManager->releaseGrab(&event.xbutton);
|
||
|
done = True;
|
||
|
break;
|
||
|
|
||
|
case MotionNotify:
|
||
|
x = event.xbutton.x; y = event.xbutton.y;
|
||
|
if (x + xoff != m_x || y + yoff != m_y) {
|
||
|
windowManager()->showGeometry(x + xoff, y + yoff);
|
||
|
m_border->moveTo(x + xoff, y + yoff);
|
||
|
doSomething = True;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
windowManager()->removeGeometry();
|
||
|
|
||
|
if (x >= 0 && doSomething) {
|
||
|
m_x = x + xoff;
|
||
|
m_y = y + yoff;
|
||
|
}
|
||
|
|
||
|
if (CONFIG_CLICK_TO_FOCUS) activate();
|
||
|
m_border->moveTo(m_x, m_y);
|
||
|
sendConfigureNotify();
|
||
|
}
|
||
|
|
||
|
|
||
|
void Client::fixResizeDimensions(int &w, int &h, int &dw, int &dh)
|
||
|
{
|
||
|
if (w < 50) w = 50;
|
||
|
if (h < 50) h = 50;
|
||
|
|
||
|
if (m_sizeHints.flags & PResizeInc) {
|
||
|
w = m_minWidth + (((w - m_minWidth) / m_sizeHints.width_inc) *
|
||
|
m_sizeHints.width_inc);
|
||
|
h = m_minHeight + (((h - m_minHeight) / m_sizeHints.height_inc) *
|
||
|
m_sizeHints.height_inc);
|
||
|
|
||
|
dw = (w - m_minWidth) / m_sizeHints.width_inc;
|
||
|
dh = (h - m_minHeight) / m_sizeHints.height_inc;
|
||
|
} else {
|
||
|
dw = w; dh = h;
|
||
|
}
|
||
|
|
||
|
if (m_sizeHints.flags & PMaxSize) {
|
||
|
if (w > m_sizeHints.max_width) w = m_sizeHints.max_width;
|
||
|
if (h > m_sizeHints.max_height) h = m_sizeHints.max_height;
|
||
|
}
|
||
|
|
||
|
if (w < m_minWidth) w = m_minWidth;
|
||
|
if (h < m_minHeight) h = m_minHeight;
|
||
|
}
|
||
|
|
||
|
|
||
|
void Client::resize(XButtonEvent *e, Boolean horizontal, Boolean vertical)
|
||
|
{
|
||
|
if (isFixedSize()) return;
|
||
|
|
||
|
if (m_windowManager->attemptGrab
|
||
|
(root(), None, DragMask, e->time) != GrabSuccess) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (vertical && horizontal)
|
||
|
m_windowManager->installCursor(WindowManager::DownrightCursor);
|
||
|
else if (vertical)
|
||
|
m_windowManager->installCursor(WindowManager::DownCursor);
|
||
|
else
|
||
|
m_windowManager->installCursor(WindowManager::RightCursor);
|
||
|
|
||
|
Window dummy;
|
||
|
XTranslateCoordinates(display(), e->window, parent(),
|
||
|
e->x, e->y, &e->x, &e->y, &dummy);
|
||
|
|
||
|
int xorig = e->x;
|
||
|
int yorig = e->y;
|
||
|
int x = xorig;
|
||
|
int y = yorig;
|
||
|
int w = m_w, h = m_h;
|
||
|
int prevW, prevH;
|
||
|
int dw, dh;
|
||
|
|
||
|
XEvent event;
|
||
|
Boolean found;
|
||
|
Boolean doSomething = False;
|
||
|
Boolean done = False;
|
||
|
struct timeval sleepval;
|
||
|
|
||
|
while (!done) {
|
||
|
|
||
|
found = False;
|
||
|
|
||
|
while (XCheckMaskEvent(display(), DragMask | ExposureMask, &event)) {
|
||
|
found = True;
|
||
|
if (event.type != MotionNotify) break;
|
||
|
}
|
||
|
|
||
|
if (!found) {
|
||
|
sleepval.tv_sec = 0;
|
||
|
sleepval.tv_usec = 50000;
|
||
|
select(0, 0, 0, 0, &sleepval);
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
switch (event.type) {
|
||
|
|
||
|
default:
|
||
|
fprintf(stderr, "wm2: unknown event type %d\n", event.type);
|
||
|
break;
|
||
|
|
||
|
case Expose:
|
||
|
m_windowManager->eventExposure(&event.xexpose);
|
||
|
break;
|
||
|
|
||
|
case ButtonPress:
|
||
|
// don't like this
|
||
|
XUngrabPointer(display(), event.xbutton.time);
|
||
|
done = True;
|
||
|
break;
|
||
|
|
||
|
case ButtonRelease:
|
||
|
|
||
|
x = event.xbutton.x; y = event.xbutton.y;
|
||
|
|
||
|
if (!nobuttons(&event.xbutton)) x = -1;
|
||
|
m_windowManager->releaseGrab(&event.xbutton);
|
||
|
|
||
|
done = True;
|
||
|
break;
|
||
|
|
||
|
case MotionNotify:
|
||
|
x = event.xbutton.x; y = event.xbutton.y;
|
||
|
|
||
|
if (vertical && horizontal) {
|
||
|
prevH = h; h = y - m_y;
|
||
|
prevW = w; w = x - m_x;
|
||
|
fixResizeDimensions(w, h, dw, dh);
|
||
|
if (h == prevH && w == prevW) break;
|
||
|
m_border->configure(m_x, m_y, w, h, CWWidth | CWHeight, 0);
|
||
|
windowManager()->showGeometry(dw, dh);
|
||
|
doSomething = True;
|
||
|
|
||
|
} else if (vertical) {
|
||
|
prevH = h; h = y - m_y;
|
||
|
fixResizeDimensions(w, h, dw, dh);
|
||
|
if (h == prevH) break;
|
||
|
m_border->configure(m_x, m_y, w, h, CWHeight, 0);
|
||
|
windowManager()->showGeometry(dw, dh);
|
||
|
doSomething = True;
|
||
|
|
||
|
} else {
|
||
|
prevW = w; w = x - m_x;
|
||
|
fixResizeDimensions(w, h, dw, dh);
|
||
|
if (w == prevW) break;
|
||
|
m_border->configure(m_x, m_y, w, h, CWWidth, 0);
|
||
|
windowManager()->showGeometry(dw, dh);
|
||
|
doSomething = True;
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (doSomething) {
|
||
|
|
||
|
windowManager()->removeGeometry();
|
||
|
|
||
|
if (vertical && horizontal) {
|
||
|
m_w = x - m_x;
|
||
|
m_h = y - m_y;
|
||
|
fixResizeDimensions(m_w, m_h, dw, dh);
|
||
|
m_border->configure(m_x, m_y, m_w, m_h, CWWidth|CWHeight, 0, True);
|
||
|
} else if (vertical) {
|
||
|
m_h = y - m_y;
|
||
|
fixResizeDimensions(m_w, m_h, dw, dh);
|
||
|
m_border->configure(m_x, m_y, m_w, m_h, CWHeight, 0, True);
|
||
|
} else {
|
||
|
m_w = x - m_x;
|
||
|
fixResizeDimensions(m_w, m_h, dw, dh);
|
||
|
m_border->configure(m_x, m_y, m_w, m_h, CWWidth, 0, True);
|
||
|
}
|
||
|
|
||
|
XMoveResizeWindow(display(), m_window,
|
||
|
m_border->xIndent(), m_border->yIndent(), m_w, m_h);
|
||
|
|
||
|
sendConfigureNotify();
|
||
|
}
|
||
|
|
||
|
m_windowManager->installCursor(WindowManager::NormalCursor);
|
||
|
}
|
||
|
|
||
|
|
||
|
void Client::moveOrResize(XButtonEvent *e)
|
||
|
{
|
||
|
if (e->x < m_border->xIndent() && e->y > m_h) {
|
||
|
resize(e, False, True);
|
||
|
} else if (e->y < m_border->yIndent() &&
|
||
|
e->x > m_w + m_border->xIndent() - m_border->yIndent()) { //hack
|
||
|
resize(e, True, False);
|
||
|
} else {
|
||
|
move(e);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
void Border::eventButton(XButtonEvent *e)
|
||
|
{
|
||
|
if (e->window == m_parent) {
|
||
|
|
||
|
if (!m_client->isActive()) return;
|
||
|
if (isTransient()) {
|
||
|
if (e->x >= xIndent() && e->y >= yIndent()) {
|
||
|
return;
|
||
|
} else {
|
||
|
m_client->move(e);
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
m_client->moveOrResize(e);
|
||
|
return;
|
||
|
|
||
|
} else if (e->window == m_tab) {
|
||
|
m_client->move(e);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (e->window == m_resize) {
|
||
|
m_client->resize(e, True, True);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (e->window != m_button || e->type == ButtonRelease) return;
|
||
|
|
||
|
if (windowManager()->attemptGrab(m_button, None, MenuGrabMask, e->time)
|
||
|
!= GrabSuccess) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
XEvent event;
|
||
|
Boolean found;
|
||
|
Boolean done = False;
|
||
|
struct timeval sleepval;
|
||
|
unsigned long tdiff = 0L;
|
||
|
int x = e->x;
|
||
|
int y = e->y;
|
||
|
int action = 1;
|
||
|
int buttonSize = m_tabWidth - TAB_TOP_HEIGHT*2 - 4;
|
||
|
|
||
|
XFillRectangle(display(), m_button, m_drawGC, 0, 0, buttonSize, buttonSize);
|
||
|
|
||
|
while (!done) {
|
||
|
|
||
|
found = False;
|
||
|
|
||
|
if (tdiff > CONFIG_DESTROY_WINDOW_DELAY && action == 1) {
|
||
|
windowManager()->installCursor(WindowManager::DeleteCursor);
|
||
|
action = 2;
|
||
|
}
|
||
|
|
||
|
while (XCheckMaskEvent(display(), MenuMask, &event)) {
|
||
|
found = True;
|
||
|
if (event.type != MotionNotify) break;
|
||
|
}
|
||
|
|
||
|
if (!found) {
|
||
|
sleepval.tv_sec = 0;
|
||
|
sleepval.tv_usec = 50000;
|
||
|
select(0, 0, 0, 0, &sleepval);
|
||
|
tdiff += 50;
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
switch (event.type) {
|
||
|
|
||
|
default:
|
||
|
fprintf(stderr, "wm2: unknown event type %d\n", event.type);
|
||
|
break;
|
||
|
|
||
|
case Expose:
|
||
|
windowManager()->eventExposure(&event.xexpose);
|
||
|
break;
|
||
|
|
||
|
case ButtonPress:
|
||
|
break;
|
||
|
|
||
|
case ButtonRelease:
|
||
|
|
||
|
if (!nobuttons(&event.xbutton)) {
|
||
|
action = 0;
|
||
|
}
|
||
|
|
||
|
if (x < 0 || y < 0 || x >= buttonSize || y >= buttonSize) {
|
||
|
action = 0;
|
||
|
}
|
||
|
|
||
|
windowManager()->releaseGrab(&event.xbutton);
|
||
|
done = True;
|
||
|
break;
|
||
|
|
||
|
case MotionNotify:
|
||
|
tdiff = event.xmotion.time - e->time;
|
||
|
if (tdiff > 5000L) tdiff = 5001L; // in case of overflow!
|
||
|
|
||
|
x = event.xmotion.x;
|
||
|
y = event.xmotion.y;
|
||
|
|
||
|
if (action == 0 || action == 2) {
|
||
|
if (x < 0 || y < 0 || x >= buttonSize || y >= buttonSize) {
|
||
|
windowManager()->installCursor(WindowManager::NormalCursor);
|
||
|
action = 0;
|
||
|
} else {
|
||
|
windowManager()->installCursor(WindowManager::DeleteCursor);
|
||
|
action = 2;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
XClearWindow(display(), m_button);
|
||
|
windowManager()->installCursor(WindowManager::NormalCursor);
|
||
|
|
||
|
if (tdiff > 5000L) { // do nothing, they dithered too long
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (action == 1) m_client->hide();
|
||
|
else if (action == 2) m_client->kill();
|
||
|
}
|
||
|
|