#include "Manager.h" #include "Client.h" #include #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 ) #define MENU_LABEL(n) ((n)==0 ? m_menuCreateLabel : \ (allowExit && ((n) > clients.count())) ? "[Exit wmG]" \ : clients.item((n)-1)->label()) void WindowManager::eventButton(XButtonEvent *e) { Client *c = windowToClient(e->window); if(e->window == e->root) { XUngrabPointer(display(), CurrentTime); if(e->send_event == False) XSendEvent(display(), root_proxy, False, SubstructureNotifyMask, (XEvent *)e); } else if(c) { c->eventButton(e); } } 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; 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(m_border->hasWindow(e->window) && e->window != m_window) { m_border->eventButton(e); } if(e->window == m_window) XSendEvent(display(), m_window, False, SubstructureNotifyMask, (XEvent *)e); if(isActive() || e->send_event) return; activate(); } static int nobuttons(XButtonEvent *e) { 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 Client::move(XButtonEvent *e) { int tmpx, tmpy, 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: doSomething = False; done = True; break; case ButtonRelease: x = event.xbutton.x; y = event.xbutton.y; if(x + xoff < 1 + m_border->xIndent()) x = 1 + m_border->xIndent() - xoff; if(y + yoff < 1 + m_border->yIndent()) y = 1 + m_border->yIndent() - yoff; if(x + xoff > DisplayWidth(display(), DefaultScreen(display())) - m_w - frame_size) x = DisplayWidth(display(), DefaultScreen(display())) - m_w - frame_size - xoff; if(y + yoff > DisplayHeight(display(), DefaultScreen(display())) - m_h - frame_size) y = DisplayHeight(display(), DefaultScreen(display())) - m_h - frame_size - yoff; if(!nobuttons(&event.xbutton)) doSomething = False; m_windowManager->releaseGrab(&event.xbutton); done = True; break; case MotionNotify: x = event.xbutton.x; y = event.xbutton.y; if(x + xoff < 1 + m_border->xIndent()) x = 1 + m_border->xIndent() - xoff; if(y + yoff < 1 + m_border->yIndent()) y = 1 + m_border->yIndent() - yoff; if(x + xoff > DisplayWidth(display(), DefaultScreen(display())) - m_w - frame_size) x = DisplayWidth(display(), DefaultScreen(display())) - m_w - frame_size - xoff; if(y + yoff > DisplayHeight(display(), DefaultScreen(display())) - m_h - frame_size) y = DisplayHeight(display(), DefaultScreen(display())) - m_h - frame_size - yoff; if(x + xoff != m_x || y + yoff != m_y) { m_border->moveTo(x + xoff, y + yoff); doSomething = True; } break; } } if(x >= 0 && doSomething) { m_x = x + xoff; m_y = y + yoff; } if(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, HDir horizontal, VDir 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, root(), e->x, e->y, &e->x, &e->y, &dummy); int xorig = e->x; int yorig = e->y; int x = xorig; int y = yorig; int x1 = m_x, y1 = m_y, x2 = m_w + x1, y2 = m_h + y1; 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: 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 == V_UP && horizontal == H_LEFT) { m_border->configure(x1 + (x - xorig), y1 + (y - yorig), x2 - x1 - (x - xorig), y2 - y1 - (y - yorig), CWX | CWY | CWWidth | CWHeight, 0); doSomething = True; } else if(vertical == V_UP && horizontal == H_RIGHT) { m_border->configure(x1, y1 + (y - yorig), x2 - x1 + (x - xorig), y2 - y1 - (y - yorig), CWX | CWY | CWWidth | CWHeight, 0); doSomething = True; } else if(vertical == V_DOWN && horizontal == H_LEFT) { m_border->configure(x1 + (x - xorig), y1, x2 - x1 - (x - xorig), y2 - y1 + (y - yorig), CWX | CWY | CWWidth | CWHeight, 0); doSomething = True; } else if(vertical == V_DOWN && horizontal == H_RIGHT) { m_border->configure(x1, y1, x2 - x1 + (x - xorig), y2 - y1 + (y - yorig), CWX | CWY | CWWidth | CWHeight, 0); doSomething = True; } else if(vertical == V_UP) { m_border->configure(x1, y1 + (y - yorig), x2 - x1, y2 - y1 - (y - yorig), CWX | CWY | CWWidth | CWHeight, 0); doSomething = True; } else if(vertical == V_DOWN) { m_border->configure(x1, y1, x2 - x1, y2 - y1 + (y - yorig), CWX | CWY | CWWidth | CWHeight, 0); doSomething = True; } else if(horizontal == H_LEFT) { m_border->configure(x1 + (x - xorig), y1, x2 - x1 - (x - xorig), y2 - y1, CWX | CWY | CWWidth | CWHeight, 0); doSomething = True; } else if(horizontal == H_RIGHT) { m_border->configure(x1, y1, x2 - x1 + (x - xorig), y2 - y1, CWX | CWY | CWWidth | CWHeight, 0); doSomething = True; } break; } } if(doSomething) { if(vertical == V_UP) { m_y = y1 + (y - yorig); m_h = y2 - y1 - (y - yorig); } else if(vertical == V_DOWN) { m_h = y2 - y1 + (y - yorig); } if(horizontal == H_LEFT) { m_x = x1 + (x - xorig); m_w = x2 - x1 - (x - xorig); } else if(horizontal == H_RIGHT) { m_w = x2 - x1 + (x - xorig); } 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 < frame_size && e->y > frame_size && e->y < m_h + frame_size) { resize(e, H_LEFT, V_NONE); } else if(e->x > m_w + frame_size && e->y > frame_size && e->y < m_h + frame_size) { resize(e, H_RIGHT, V_NONE); } else if(e->y < frame_size && e->x > frame_size && e->x < m_w + frame_size) { resize(e, H_NONE, V_UP); } else if(e->y > m_h + frame_size && e->x > frame_size && e->x < m_w + frame_size) { resize(e, H_NONE, V_DOWN); } else if(e->y < frame_size && e->x > m_w + frame_size) { resize(e, H_RIGHT, V_UP); } else if(e->y < frame_size && e->x < frame_size) { resize(e, H_LEFT, V_UP); } else if(e->y > m_h + frame_size && e->x > m_w + frame_size) { resize(e, H_RIGHT, V_DOWN); } else if(e->y > m_h + frame_size && e->x < frame_size) { resize(e, H_LEFT, V_DOWN); } else { move(e); } } void Border::eventButton(XButtonEvent *e) { if(e->window == m_parent) { 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) { if(e->button == Button2) maximize(); else if(e->button == Button1) m_client->move(e); return; } if(e->window == m_hideButton && e->type == ButtonPress) { if(windowManager()->attemptGrab(m_hideButton, 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 = title_size - 4; XFillRectangle(display(), m_hideButton, m_drawGC, 0, 0, buttonSize, buttonSize); while(!done) { found = False; while(XCheckMaskEvent(display(), MenuMask, &event)) { found = True; if(event.type != MotionNotify) break; } if(!found) 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: x = event.xmotion.x; y = event.xmotion.y; if(action == 0 || action == 2) { if(x < 0 || y < 0 || x >= buttonSize || y >= buttonSize) { action = 0; } else { action = 1; } } break; } } XClearWindow(display(), m_hideButton); if(action == 1) m_client->hide(); } else if(e->window == m_closeButton && e->type == ButtonPress) { if(windowManager()->attemptGrab(m_closeButton, 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 = title_size - 4; XFillRectangle(display(), m_closeButton, m_drawGC, 0, 0, buttonSize, buttonSize); windowManager()->installCursor(WindowManager::DeleteCursor); while(!done) { found = False; while(XCheckMaskEvent(display(), MenuMask, &event)) { found = True; if(event.type != MotionNotify) break; } if(!found) 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: 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 = 1; } } break; } } XClearWindow(display(), m_closeButton); windowManager()->installCursor(WindowManager::NormalCursor); if(action == 1) m_client->kill(); } } void Border::maximize() { int x, y, w, h, x1, x2, y1, y2; if(!isFixedSize()) { int i, num; y = m_client->m_y; h = m_client->m_h; y1 = yIndent(); y2 = DisplayHeight(display(), DefaultScreen(display())) - frame_size; x = m_client->m_x; w = m_client->m_w; x1 = xIndent(); x2 = DisplayWidth(display(), DefaultScreen(display())) - frame_size; for(i = 0; i < windowManager()->m_clients.count() - 1; i++) { if(windowManager()->m_clients.item(i)->handle() != m_client->handle()) { if((((windowManager()->m_clients.item(i)->m_y + windowManager()->m_clients.item(i)->m_h) <= y) && ((windowManager()->m_clients.item(i)->m_y + windowManager()->m_clients.item(i)->m_h) >= y1))) y1 = windowManager()->m_clients.item(i)->m_y + windowManager()->m_clients.item(i)->m_h; else if(((y + h) <= windowManager()->m_clients.item(i)->m_y) && (y2 >= windowManager()->m_clients.item(i)->m_y)) y2 = windowManager()->m_clients.item(i)->m_y - (windowManager()->m_clients.item(i)->m_managed ? windowManager()->m_clients.item(i)->m_border->yIndent() : 0); } } y = y1; h = y2 - y1; for(i = 0; i < windowManager()->m_clients.count() - 1; i++) { if(windowManager()->m_clients.item(i)->handle() != m_client->handle()) { if((((windowManager()->m_clients.item(i)->m_x + windowManager()->m_clients.item(i)->m_w) <= x) && ((windowManager()->m_clients.item(i)->m_x + windowManager()->m_clients.item(i)->m_w) >= x1))) x1 = windowManager()->m_clients.item(i)->m_x + windowManager()->m_clients.item(i)->m_w; else if(((x + w) <= windowManager()->m_clients.item(i)->m_x) && (x2 >= windowManager()->m_clients.item(i)->m_x)) x2 = windowManager()->m_clients.item(i)->m_x - (windowManager()->m_clients.item(i)->m_managed ? windowManager()->m_clients.item(i)->m_border->xIndent() : 0); } } x = x1; w = x2 - x1; m_client->m_x = x; m_client->m_y = y; m_client->m_w = w; m_client->m_h = h; configure(x, y, w, h, 0, 0); XMoveResizeWindow(display(), m_client->m_window, xIndent(), yIndent(), w, h); } return; }