wmfs/src/event.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;
}