Skip to content
Snippets Groups Projects
events.c 81.1 KiB
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; either version 2, or (at your option)
        any later 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.
Olivier Fourdan's avatar
Olivier Fourdan committed
        oroborus - (c) 2001 Ken Lynch
        xfwm4    - (c) 2002-2006 Olivier Fourdan
Olivier Fourdan's avatar
Olivier Fourdan committed
 */

#ifdef HAVE_CONFIG_H
Olivier Fourdan's avatar
Olivier Fourdan committed
#endif

#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/extensions/shape.h>
Olivier Fourdan's avatar
Olivier Fourdan committed
#include <gdk/gdk.h>
Olivier Fourdan's avatar
Olivier Fourdan committed
#include <gdk/gdkx.h>
Olivier Fourdan's avatar
Olivier Fourdan committed
#ifdef HAVE_RANDR
#include <X11/extensions/Xrandr.h>
#endif
#include <libxfce4util/libxfce4util.h>
#include <string.h>

Olivier Fourdan's avatar
Olivier Fourdan committed
#include "misc.h"
Olivier Fourdan's avatar
Olivier Fourdan committed
#include "workspaces.h"
#include "settings.h"
Olivier Fourdan's avatar
Olivier Fourdan committed
#include "mywindow.h"
Olivier Fourdan's avatar
Olivier Fourdan committed
#include "frame.h"
#include "client.h"
Olivier Fourdan's avatar
Olivier Fourdan committed
#include "menu.h"
Olivier Fourdan's avatar
Olivier Fourdan committed
#include "hints.h"
#include "startup_notification.h"
Olivier Fourdan's avatar
Olivier Fourdan committed
#include "compositor.h"
Olivier Fourdan's avatar
Olivier Fourdan committed

#ifndef CHECK_BUTTON_TIME
#define CHECK_BUTTON_TIME 0
#endif

#define WIN_IS_BUTTON(win)      ((win == MYWINDOW_XWINDOW(c->buttons[HIDE_BUTTON])) || \
                                 (win == MYWINDOW_XWINDOW(c->buttons[CLOSE_BUTTON])) || \
                                 (win == MYWINDOW_XWINDOW(c->buttons[MAXIMIZE_BUTTON])) || \
                                 (win == MYWINDOW_XWINDOW(c->buttons[SHADE_BUTTON])) || \
                                 (win == MYWINDOW_XWINDOW(c->buttons[STICK_BUTTON])))

#define DBL_CLICK_GRAB          (ButtonMotionMask | \
                                 PointerMotionMask | \
                                 ButtonPressMask | \
                                 ButtonReleaseMask)
#define MODIFIER_MASK           (ShiftMask | \
                                 ControlMask | \
                                 AltMask | \
                                 MetaMask | \
                                 SuperMask | \
                                 HyperMask)
Olivier Fourdan's avatar
Olivier Fourdan committed
static guint raise_timeout = 0;
static GdkAtom atom_rcfiles = GDK_NONE;
static xfwmWindow menu_event_window;
Olivier Fourdan's avatar
Olivier Fourdan committed

/* Forward decl. */

static void handleEvent         (DisplayInfo *display_info,
                                 XEvent * ev);
static void menu_callback       (Menu * menu,
                                 MenuOp op,
                                 Window xid,
                                 gpointer menu_data,
                                 gpointer item_data);
static void show_window_menu    (Client *c,
                                 gint px,
                                 gint py,
                                 guint button,
                                 guint32 time);
static gboolean show_popup_cb   (GtkWidget * widget,
                                 GdkEventButton * ev,
                                 gpointer data);
static gboolean client_event_cb (GtkWidget * widget,
                                 GdkEventClient * ev,
                                 gpointer data);
Olivier Fourdan's avatar
Olivier Fourdan committed

typedef enum
{
    XFWM_BUTTON_UNDEFINED = 0,
    XFWM_BUTTON_DRAG = 1,
    XFWM_BUTTON_CLICK = 2,
    XFWM_BUTTON_CLICK_AND_DRAG = 3,
    XFWM_BUTTON_DOUBLE_CLICK = 4
}
XfwmButtonClickType;
typedef struct _XfwmButtonClickData XfwmButtonClickData;
struct _XfwmButtonClickData
{
    DisplayInfo *display_info;
Olivier Fourdan's avatar
Olivier Fourdan committed
    guint timeout;
Olivier Fourdan's avatar
Olivier Fourdan committed
    gboolean allow_double_click;
Olivier Fourdan's avatar
Olivier Fourdan committed
    XfwmButtonClickData *passdata;

    passdata = (XfwmButtonClickData *) data;
    if (passdata->timeout)
    {
        g_source_remove (passdata->timeout);
        passdata->timeout = 0;
    }

    gtk_main_quit ();

    return (TRUE);
}

static eventFilterStatus
typeOfClick_event_filter (XEvent * xevent, gpointer data)
{
Olivier Fourdan's avatar
Olivier Fourdan committed
    XfwmButtonClickData *passdata;
    eventFilterStatus status;
    gboolean keep_going;

    keep_going = TRUE;
    passdata = (XfwmButtonClickData *) data;
    status = EVENT_FILTER_STOP;

    /* Update the display time */
    myDisplayUpdateCurrentTime (passdata->display_info, xevent);
    if ((xevent->type == ButtonRelease) || (xevent->type == ButtonPress))
    {
        if (xevent->xbutton.button == passdata->button)
        {
            passdata->clicks++;
        }
        if (((XfwmButtonClickType) passdata->clicks == XFWM_BUTTON_DOUBLE_CLICK)
            || (!(passdata->allow_double_click) &&
                 (XfwmButtonClickType) passdata->clicks == XFWM_BUTTON_CLICK))
        {
            keep_going = FALSE;
        }
    }
    else if (xevent->type == MotionNotify)
    {
        passdata->xcurrent = xevent->xmotion.x_root;
        passdata->ycurrent = xevent->xmotion.y_root;
    }
    else if ((xevent->type == DestroyNotify) || (xevent->type == UnmapNotify))
    {
        if (xevent->xany.window == passdata->w)
        {
            /* Discard, mark the click as undefined */
            passdata->clicks = (guint) XFWM_BUTTON_UNDEFINED;
            keep_going = FALSE;
        }
        status = EVENT_FILTER_CONTINUE;
        status = EVENT_FILTER_CONTINUE;
    if ((ABS (passdata->x - passdata->xcurrent) > 1) ||
        (ABS (passdata->y - passdata->ycurrent) > 1) ||
        (!keep_going))
    {
        TRACE ("event loop now finished");
        typeOfClick_break (data);
Loading
Loading full blame...