Newer
Older
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; You may only use version 2 of the License,
you have no option to use any other version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
oroborus - (c) 2001 Ken Lynch
xfwm4 - (c) 2002 Olivier Fourdan
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <X11/Xatom.h>
#include <libxfcegui4/libxfcegui4.h>
#include "main.h"
#include "workspaces.h"
#include "settings.h"
#include "frame.h"
#include "client.h"
#include "menu.h"
#include "startup_notification.h"
static guint raise_timeout = 0;
static gulong button_handler_id = 0;
static GdkAtom atom_rcfiles = GDK_NONE;
Olivier Fourdan
committed
static void menu_callback(Menu * menu, MenuOp op, Window client_xwindow, gpointer menu_data, gpointer item_data);
static gboolean show_popup_cb(GtkWidget * widget, GdkEventButton * ev, gpointer data);
static gboolean client_event_cb(GtkWidget * widget, GdkEventClient * ev);
Olivier Fourdan
committed
XFWM_BUTTON_UNDEFINED = 0,
XFWM_BUTTON_DRAG = 1,
XFWM_BUTTON_CLICK = 2,
XFWM_BUTTON_CLICK_AND_DRAG = 3,
XFWM_BUTTON_DOUBLE_CLICK = 4
}
XfwmButtonClickType;
static inline XfwmButtonClickType typeOfClick(Window w, XEvent * ev, gboolean allow_double_click)
Olivier Fourdan
committed
{
Olivier Fourdan
committed
int xcurrent, ycurrent, x, y, total;
Olivier Fourdan
committed
int g = GrabSuccess;
Olivier Fourdan
committed
int clicks;
Time t0, t1;
Olivier Fourdan
committed
g_return_val_if_fail(ev != NULL, XFWM_BUTTON_UNDEFINED);
g_return_val_if_fail(w != None, XFWM_BUTTON_UNDEFINED);
Olivier Fourdan
committed
g = XGrabPointer(dpy, w, False, ButtonMotionMask | PointerMotionMask | PointerMotionHintMask | ButtonPressMask | ButtonReleaseMask, GrabModeAsync, GrabModeAsync, None, None, ev->xbutton.time);
if(g != GrabSuccess)
Olivier Fourdan
committed
{
DBG("grab failed in typeOfClick\n");
gdk_beep();
return XFWM_BUTTON_UNDEFINED;
}
Olivier Fourdan
committed
Olivier Fourdan
committed
x = xcurrent = ev->xbutton.x_root;
y = ycurrent = ev->xbutton.y_root;
Olivier Fourdan
committed
t0 = ev->xbutton.time;
t1 = t0;
total = 0;
clicks = 1;
Olivier Fourdan
committed
while((ABS(x - xcurrent) < 1) && (ABS(y - ycurrent) < 1) && (total < params.dbl_click_time) && ((t1 - t0) < params.dbl_click_time))
Olivier Fourdan
committed
{
Olivier Fourdan
committed
g_usleep(10000);
Olivier Fourdan
committed
total += 10;
Olivier Fourdan
committed
if(XCheckMaskEvent(dpy, ButtonReleaseMask | ButtonPressMask, ev))
Olivier Fourdan
committed
{
Olivier Fourdan
committed
if(ev->xbutton.button == button)
{
clicks++;
}
t1 = ev->xbutton.time;
Olivier Fourdan
committed
}
Olivier Fourdan
committed
if(XCheckMaskEvent(dpy, ButtonMotionMask | PointerMotionMask | PointerMotionHintMask, ev))
Olivier Fourdan
committed
{
xcurrent = ev->xmotion.x_root;
ycurrent = ev->xmotion.y_root;
Olivier Fourdan
committed
t1 = ev->xmotion.time;
Olivier Fourdan
committed
}
if((XfwmButtonClickType) clicks == XFWM_BUTTON_DOUBLE_CLICK || (!allow_double_click && (XfwmButtonClickType) clicks == XFWM_BUTTON_CLICK))
Olivier Fourdan
committed
{
break;
}
}
XUngrabPointer(dpy, ev->xbutton.time);
return (XfwmButtonClickType) clicks;
}
Olivier Fourdan
committed
static void clear_timeout(void)
Olivier Fourdan
committed
if(raise_timeout)
Olivier Fourdan
committed
gtk_timeout_remove(raise_timeout);
raise_timeout = 0;
Olivier Fourdan
committed
static gboolean raise_cb(gpointer data)
Olivier Fourdan
committed
clear_timeout();
c = clientGetFocus();
if(c)
{
clientRaise(c);
}
return (TRUE);
}
Olivier Fourdan
committed
static void reset_timeout(void)
Olivier Fourdan
committed
if(raise_timeout)
Olivier Fourdan
committed
gtk_timeout_remove(raise_timeout);
raise_timeout = gtk_timeout_add(params.raise_delay, (GtkFunction) raise_cb, NULL);
Olivier Fourdan
committed
static inline void _moveRequest(Client * c, XEvent * ev)
if(CLIENT_FLAG_TEST_AND_NOT(c, CLIENT_FLAG_HAS_BORDER | CLIENT_FLAG_HAS_MOVE, CLIENT_FLAG_FULLSCREEN))
{
clientMove(c, ev);
}
}
Olivier Fourdan
committed
static inline void _resizeRequest(Client * c, int corner, XEvent * ev)
{
clientSetFocus(c, True);
if(CLIENT_FLAG_TEST_ALL(c, CLIENT_FLAG_HAS_RESIZE | CLIENT_FLAG_IS_RESIZABLE))
Olivier Fourdan
committed
clientResize(c, corner, ev);
else if(CLIENT_FLAG_TEST_AND_NOT(c, CLIENT_FLAG_HAS_BORDER | CLIENT_FLAG_HAS_MOVE, CLIENT_FLAG_FULLSCREEN))
Olivier Fourdan
committed
clientMove(c, ev);
static inline void spawn_shortcut(int i)
{
GError *error = NULL;
if((i >= NB_KEY_SHORTCUTS) || (!params.shortcut_exec[i]) || !strlen(params.shortcut_exec[i]))
{
return;
}
if(!g_spawn_command_line_async(params.shortcut_exec[i], &error))
if(error)
{
g_warning("%s: %s", g_get_prgname(), error->message);
g_error_free(error);
}
static inline void handleKeyPress(XKeyEvent * ev)
{
Client *c;
int state, key;
XEvent e;
DBG("entering handleKeyEvent\n");
c = clientGetFocus();
state = ev->state & (ShiftMask | ControlMask | AltMask | MetaMask | SuperMask | HyperMask);
if((params.keys[key].keycode == ev->keycode) && (params.keys[key].modifier == state))
Olivier Fourdan
committed
{
Loading
Loading full blame...