384 lines
10 KiB
C
384 lines
10 KiB
C
/*
|
|
* event.c
|
|
* Copyright © 2008 Martin Duquesnoy <xorg62@gmail.com>
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions are
|
|
* met:
|
|
*
|
|
* * Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* * Redistributions in binary form must reproduce the above
|
|
* copyright notice, this list of conditions and the following disclaimer
|
|
* in the documentation and/or other materials provided with the
|
|
* distribution.
|
|
* * Neither the name of the nor the names of its
|
|
* contributors may be used to endorse or promote products derived from
|
|
* this software without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
#include "wmfs.h"
|
|
|
|
/** ButtonPress handle event
|
|
* \param ev XButtonEvent pointer
|
|
*/
|
|
void
|
|
buttonpress(XButtonEvent *ev)
|
|
{
|
|
Client *c;
|
|
int i;
|
|
char s[6];
|
|
|
|
/* Titlebar */
|
|
if((c = client_gb_titlebar(ev->window)))
|
|
for(i = 0; i < conf.titlebar.nmouse; ++i)
|
|
if(ev->button == conf.titlebar.mouse[i].button)
|
|
if(conf.titlebar.mouse[i].func)
|
|
conf.titlebar.mouse[i].func(conf.titlebar.mouse[i].cmd);
|
|
|
|
/* Frame Resize Area */
|
|
if((c = client_gb_resize(ev->window)))
|
|
mouse_resize(c);
|
|
|
|
/* Client */
|
|
if((c = client_gb_win(ev->window)))
|
|
for(i = 0; i < conf.client.nmouse; ++i)
|
|
if(ev->button == conf.client.mouse[i].button)
|
|
if(conf.client.mouse[i].func)
|
|
conf.client.mouse[i].func(conf.client.mouse[i].cmd);
|
|
|
|
/* Root */
|
|
if(ev->window == root)
|
|
for(i = 0; i < conf.root.nmouse; ++i)
|
|
if(ev->button == conf.root.mouse[i].button)
|
|
if(conf.root.mouse[i].func)
|
|
conf.root.mouse[i].func(conf.root.mouse[i].cmd);
|
|
|
|
/* Tag */
|
|
for(i = 1; i < conf.ntag + 1; ++i)
|
|
{
|
|
ITOA(s, i);
|
|
if(ev->window == infobar->tags[i]->win)
|
|
{
|
|
if(ev->button == Button1)
|
|
uicb_tag(s);
|
|
if(ev->button == Button3)
|
|
uicb_tagtransfert(s);
|
|
if(ev->button == Button4)
|
|
uicb_tag("+1");
|
|
if (ev->button == Button5)
|
|
uicb_tag("-1");
|
|
}
|
|
}
|
|
|
|
/* Layout button */
|
|
if(ev->window == infobar->layout_button->win)
|
|
{
|
|
if(ev->button == Button1
|
|
|| ev->button == Button4)
|
|
layoutswitch(True);
|
|
if(ev->button == Button3
|
|
|| ev->button == Button5)
|
|
layoutswitch(False);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
/** ConfigureRequest & ConfigureNotify handle event
|
|
* \param ev XEvent pointer
|
|
*/
|
|
void
|
|
configureevent(XEvent *ev)
|
|
{
|
|
XWindowChanges wc;
|
|
XWindowAttributes win_at, ev_at;
|
|
XRectangle geo = { 0 };
|
|
Client *c;
|
|
|
|
/* Check part */
|
|
if((c = client_gb_win(ev->xconfigurerequest.window))
|
|
|| (c = client_gb_win(ev->xconfigure.window)))
|
|
{
|
|
CHECK(!c->tile);
|
|
CHECK(!c->lmax);
|
|
}
|
|
|
|
/* Configure Request Part {{{ */
|
|
wc.x = ev->xconfigurerequest.x;
|
|
wc.y = ev->xconfigurerequest.y;
|
|
wc.width = ev->xconfigurerequest.width;
|
|
wc.height = ev->xconfigurerequest.height;
|
|
wc.border_width = ev->xconfigurerequest.border_width;
|
|
wc.sibling = ev->xconfigurerequest.above;
|
|
wc.stack_mode = ev->xconfigurerequest.detail;
|
|
XConfigureWindow(dpy, ev->xconfigurerequest.window,
|
|
ev->xconfigurerequest.value_mask, &wc);
|
|
/* }}} */
|
|
|
|
/* Configure Notify Part {{{*/
|
|
if((c = client_gb_win(ev->xconfigure.window)))
|
|
{
|
|
XGetWindowAttributes(dpy, ev->xconfigure.window, &win_at);
|
|
XGetWindowAttributes(dpy, ev->xconfigure.event, &ev_at);
|
|
|
|
/* Frame config */
|
|
if(win_at.width != ev_at.width
|
|
|| win_at.height != ev_at.height)
|
|
{
|
|
c->geo.width = geo.width = ev->xconfigure.width;
|
|
c->geo.height = geo.height = ev->xconfigure.height;
|
|
frame_moveresize(c, geo);
|
|
}
|
|
|
|
/* Win config (re-adjust it with the frame) */
|
|
if(ev->xconfigure.x != BORDH
|
|
|| ev->xconfigure.y != BORDH + TBARH)
|
|
XMoveWindow(dpy, ev->xconfigure.window, BORDH, BORDH + TBARH);
|
|
}
|
|
/* }}} */
|
|
|
|
return;
|
|
}
|
|
|
|
/** DestroyNotify handle event
|
|
* \param ev XDestroyWindowEvent pointer
|
|
*/
|
|
void
|
|
destroynotify(XDestroyWindowEvent *ev)
|
|
{
|
|
Client *c;
|
|
|
|
if((c = client_gb_win(ev->window)))
|
|
{
|
|
client_unmanage(c);
|
|
XSetErrorHandler(errorhandler);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
/** EnterNotify handle event
|
|
* \param ev XCrossingEvent pointer
|
|
*/
|
|
void
|
|
enternotify(XCrossingEvent *ev)
|
|
{
|
|
Client *c;
|
|
|
|
if(ev->mode != NotifyNormal
|
|
|| ev->detail == NotifyInferior)
|
|
return;
|
|
if((c = client_gb_win(ev->window))
|
|
|| (c = client_gb_frame(ev->window))
|
|
|| (c = client_gb_titlebar(ev->window)))
|
|
client_focus(c);
|
|
else
|
|
client_focus(NULL);
|
|
|
|
return;
|
|
}
|
|
|
|
/** ExposeEvent handle event
|
|
* \param ev XExposeEvent pointer
|
|
*/
|
|
void
|
|
expose(XExposeEvent *ev)
|
|
{
|
|
Client *c;
|
|
int i;
|
|
|
|
if(ev->count == 0
|
|
&& (ev->window == infobar->bar->win))
|
|
bar_refresh(infobar->bar);
|
|
|
|
for(i = 1; i < conf.ntag + 1; ++i)
|
|
if(ev->window == infobar->tags[i]->win)
|
|
bar_refresh(infobar->tags[i]);
|
|
|
|
if(ev->window == infobar->layout_button->win)
|
|
bar_refresh(infobar->layout_button);
|
|
|
|
if((c = client_gb_titlebar(ev->window)))
|
|
frame_update(c);
|
|
|
|
return;
|
|
}
|
|
|
|
/** FocusChange handle event
|
|
* \param ev XFocusChangeEvent pointer
|
|
* \return
|
|
*/
|
|
void
|
|
focusin(XFocusChangeEvent *ev)
|
|
{
|
|
if(sel && ev->window != sel->win)
|
|
client_focus(sel);
|
|
|
|
return;
|
|
}
|
|
|
|
/** Key grabbing function
|
|
*/
|
|
void
|
|
grabkeys(void)
|
|
{
|
|
uint i, j;
|
|
KeyCode code;
|
|
uint ml[] = {LockMask,
|
|
numlockmask,
|
|
scrolllockmask,
|
|
numlockmask|scrolllockmask,
|
|
LockMask|scrolllockmask,
|
|
LockMask|numlockmask,
|
|
LockMask|numlockmask|scrolllockmask};
|
|
|
|
XUngrabKey(dpy, AnyKey, AnyModifier, root);
|
|
for(i = 0; i < conf.nkeybind; ++i)
|
|
{
|
|
code = XKeysymToKeycode(dpy, keys[i].keysym);
|
|
for(j = 0; j < (sizeof ml / sizeof ml[0]); ++j)
|
|
XGrabKey(dpy, code, keys[i].mod|ml[j], root, True, GrabModeAsync, GrabModeAsync);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
/** KeyPress handle event
|
|
* \param ev XKeyPressedEvent pointer
|
|
*/
|
|
void
|
|
keypress(XKeyPressedEvent *ev)
|
|
{
|
|
uint i;
|
|
KeySym keysym;
|
|
|
|
keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0);
|
|
for(i = 0; i < conf.nkeybind; ++i)
|
|
if(keysym == keys[i].keysym
|
|
&& (keys[i].mod & ~(numlockmask | LockMask | scrolllockmask))
|
|
== (ev->state & ~(numlockmask | LockMask | scrolllockmask))
|
|
&& keys[i].func)
|
|
keys[i].func(keys[i].cmd);
|
|
|
|
return;
|
|
}
|
|
|
|
/** MapNotify handle event
|
|
* \param ev XMappingEvent pointer
|
|
*/
|
|
void
|
|
mappingnotify(XMappingEvent *ev)
|
|
{
|
|
if(ev->request == MappingKeyboard)
|
|
grabkeys();
|
|
|
|
return;
|
|
}
|
|
|
|
/** MapRequest handle event
|
|
* \param ev XMapRequestEvent pointer
|
|
*/
|
|
void
|
|
maprequest(XMapRequestEvent *ev)
|
|
{
|
|
XWindowAttributes at;
|
|
Client *c;
|
|
|
|
CHECK(XGetWindowAttributes(dpy, ev->window, &at));
|
|
CHECK(!at.override_redirect);
|
|
if(!(c = client_gb_win(ev->window)))
|
|
client_manage(ev->window, &at);
|
|
else
|
|
client_map(c);
|
|
|
|
return;
|
|
}
|
|
|
|
/** PropertyNotify handle event
|
|
* \param ev XPropertyEvent pointer
|
|
*/
|
|
void
|
|
propertynotify(XPropertyEvent *ev)
|
|
{
|
|
Client *c;
|
|
Window trans;
|
|
|
|
if(ev->state == PropertyDelete)
|
|
return;
|
|
if((c = client_gb_win(ev->window)))
|
|
{
|
|
switch(ev->atom)
|
|
{
|
|
default: break;
|
|
case XA_WM_TRANSIENT_FOR:
|
|
XGetTransientForHint(dpy, c->win, &trans);
|
|
if((c->tile || c->max) && (c->hint = (client_gb_win(trans) != NULL)))
|
|
arrange();
|
|
break;
|
|
case XA_WM_NORMAL_HINTS:
|
|
client_size_hints(c);
|
|
break;
|
|
}
|
|
if(ev->atom == XA_WM_NAME
|
|
|| ev->atom == net_atom[NetWMName])
|
|
client_get_name(c);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
/** UnmapNotify handle event
|
|
* \param ev XUnmapEvent pointer
|
|
*/
|
|
void
|
|
unmapnotify(XUnmapEvent *ev)
|
|
{
|
|
Client *c;
|
|
|
|
if((c = client_gb_win(ev->window))
|
|
&& ev->send_event)
|
|
client_unmanage(c);
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
/** Event handle function: execute every function
|
|
* handle by event
|
|
* \param ev Event
|
|
*/
|
|
void
|
|
getevent(XEvent ev)
|
|
{
|
|
switch (ev.type)
|
|
{
|
|
case ButtonPress: buttonpress(&ev.xbutton); break;
|
|
case ConfigureRequest: configureevent(&ev); break;
|
|
case DestroyNotify: destroynotify(&ev.xdestroywindow); break;
|
|
case EnterNotify: enternotify(&ev.xcrossing); break;
|
|
case Expose: expose(&ev.xexpose); break;
|
|
case FocusIn: focusin(&ev.xfocus); break;
|
|
case KeyPress: keypress(&ev.xkey); break;
|
|
case MapRequest: maprequest(&ev.xmaprequest); break;
|
|
case MappingNotify: mappingnotify(&ev.xmapping); break;
|
|
case PropertyNotify: propertynotify(&ev.xproperty); break;
|
|
case UnmapNotify: unmapnotify(&ev.xunmap); break;
|
|
}
|
|
|
|
return;
|
|
}
|