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., Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA.
#include <string.h>
Olivier Fourdan
committed
#include <X11/X.h>
#include <X11/Xatom.h>
#include <glib.h>
#include <gtk/gtk.h>
#ifdef HAVE_RANDR
#include <X11/extensions/Xrandr.h>
#endif
#include <libxfce4util/libxfce4util.h>
#include "moveresize.h"
#include "cycle.h"
#include "placement.h"
#include "stacking.h"
Olivier Fourdan
committed
#include "transients.h"
#include "focus.h"
#include "netwm.h"
#include "startup_notification.h"
#include "events.h"
#include "event_filter.h"
Olivier Fourdan
committed
#include "xsync.h"
Olivier Fourdan
committed
#ifndef CHECK_BUTTON_TIME
#define CHECK_BUTTON_TIME 0
#endif
Olivier Fourdan
committed
#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)
Olivier Fourdan
committed
static int edge_scroll_x = 0;
Olivier Fourdan
committed
static int edge_scroll_y = 0;
Olivier Fourdan
committed
/* Forward decl. */
static eventFilterStatus 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
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;
Olivier Fourdan
committed
typedef struct _XfwmButtonClickData XfwmButtonClickData;
struct _XfwmButtonClickData
{
Olivier Fourdan
committed
Window w;
guint button;
guint clicks;
Olivier Fourdan
committed
gint x;
gint y;
gint xcurrent;
gint ycurrent;
Olivier Fourdan
committed
};
static gboolean
typeOfClick_break (gpointer data)
{
XfwmButtonClickData *passdata;
passdata = (XfwmButtonClickData *) data;
Olivier Fourdan
committed
if (passdata->timeout)
{
g_source_remove (passdata->timeout);
passdata->timeout = 0;
}
gtk_main_quit ();
return (TRUE);
}
Olivier Fourdan
committed
typeOfClick_event_filter (XEvent * xevent, gpointer data)
{
XfwmButtonClickData *passdata;
eventFilterStatus status;
gboolean keep_going;
keep_going = TRUE;
passdata = (XfwmButtonClickData *) data;
status = EVENT_FILTER_STOP;
myDisplayUpdateCurrentTime (passdata->display_info, xevent);
Olivier Fourdan
committed
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) &&
Olivier Fourdan
committed
(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;
}
Olivier Fourdan
committed
}
else
{
Olivier Fourdan
committed
}
if ((ABS (passdata->x - passdata->xcurrent) > 1) ||
Olivier Fourdan
committed
(ABS (passdata->y - passdata->ycurrent) > 1) ||
(!keep_going))
{
TRACE ("event loop now finished");
typeOfClick_break (data);
}
return status;
}
Olivier Fourdan
committed
typeOfClick (ScreenInfo *screen_info, Window w, XEvent * ev, gboolean allow_double_click)
Olivier Fourdan
committed
{
Olivier Fourdan
committed
XfwmButtonClickData passdata;
Olivier Fourdan
committed
Olivier Fourdan
committed
g_return_val_if_fail (screen_info != NULL, XFWM_BUTTON_UNDEFINED);
g_return_val_if_fail (ev != NULL, XFWM_BUTTON_UNDEFINED);
g_return_val_if_fail (w != None, XFWM_BUTTON_UNDEFINED);
display_info = screen_info->display_info;
g = myScreenGrabPointer (screen_info, DBL_CLICK_GRAB, None, ev->xbutton.time);
if (!g)
Olivier Fourdan
committed
{
TRACE ("grab failed in typeOfClick");
gdk_beep ();
myScreenUngrabPointer (screen_info, ev->xbutton.time);
return XFWM_BUTTON_UNDEFINED;
Olivier Fourdan
committed
}
Olivier Fourdan
committed
passdata.display_info = display_info;
Olivier Fourdan
committed
passdata.button = ev->xbutton.button;
passdata.w = w;
passdata.x = ev->xbutton.x_root;
passdata.y = ev->xbutton.y_root;
passdata.xcurrent = passdata.x;
passdata.ycurrent = passdata.y;
passdata.clicks = 1;
passdata.allow_double_click = allow_double_click;
passdata.timeout = g_timeout_add_full (G_PRIORITY_DEFAULT,
Olivier Fourdan
committed
display_info->dbl_click_time,
Olivier Fourdan
committed
(gpointer) &passdata, NULL);
Olivier Fourdan
committed
TRACE ("entering typeOfClick loop");
eventFilterPush (display_info->xfilter, typeOfClick_event_filter, &passdata);
Olivier Fourdan
committed
gtk_main ();
eventFilterPop (display_info->xfilter);
Olivier Fourdan
committed
TRACE ("leaving typeOfClick loop");
myScreenUngrabPointer (screen_info, myDisplayGetCurrentTime (display_info));
Olivier Fourdan
committed
return (XfwmButtonClickType) passdata.clicks;
Olivier Fourdan
committed
}
Olivier Fourdan
committed
#if CHECK_BUTTON_TIME
Olivier Fourdan
committed
static gboolean
check_button_time (XButtonEvent *ev)
{
static guint32 last_button_time = CurrentTime;
Olivier Fourdan
committed
if (last_button_time > ev->time)
{
return FALSE;
}
last_button_time = ev->time;
return TRUE;
}
Olivier Fourdan
committed
#endif
static void
toggle_show_desktop (ScreenInfo *screen_info)
{
screen_info->show_desktop = !screen_info->show_desktop;
setHint (screen_info->display_info, screen_info->xroot, NET_SHOWING_DESKTOP,
sendRootMessage (screen_info, NET_SHOWING_DESKTOP, screen_info->show_desktop,
myDisplayGetCurrentTime (screen_info->display_info));
static eventFilterStatus
handleMotionNotify (DisplayInfo *display_info, XMotionEvent * ev)
Olivier Fourdan
committed
{
TRACE ("entering handleMotionNotify");
return EVENT_FILTER_REMOVE;
Olivier Fourdan
committed
}
static eventFilterStatus
handleKeyPress (DisplayInfo *display_info, XKeyEvent * ev)
{
eventFilterStatus status;
ScreenInfo *ev_screen_info;
gboolean handled;
int key;
TRACE ("entering handleKeyEvent");
ev_screen_info = myDisplayGetScreenFromRoot (display_info, ev->root);
if (!ev_screen_info)
{
XAllowEvents (display_info->dpy, AsyncKeyboard, ev->time);
}
handled = FALSE;
key = myScreenGetKeyPressed (screen_info, ev);
status = EVENT_FILTER_REMOVE;
Olivier Fourdan
committed
switch (key)
{
handled = TRUE;
XAllowEvents (display_info->dpy, AsyncKeyboard, ev->time);
handled = TRUE;
XAllowEvents (display_info->dpy, AsyncKeyboard, ev->time);
break;
case KEY_CYCLE_WINDOWS:
case KEY_CYCLE_REVERSE_WINDOWS:
handled = TRUE;
XAllowEvents (display_info->dpy, AsyncKeyboard, ev->time);
break;
case KEY_CLOSE_WINDOW:
handled = TRUE;
XAllowEvents (display_info->dpy, AsyncKeyboard, ev->time);
clientClose (c);
break;
case KEY_HIDE_WINDOW:
handled = TRUE;
XAllowEvents (display_info->dpy, AsyncKeyboard, ev->time);
Olivier Fourdan
committed
clientWithdraw (c, c->win_workspace, TRUE);
break;
case KEY_MAXIMIZE_WINDOW:
handled = TRUE;
XAllowEvents (display_info->dpy, AsyncKeyboard, ev->time);
clientToggleMaximized (c, WIN_STATE_MAXIMIZED, TRUE);
break;
case KEY_MAXIMIZE_VERT:
handled = TRUE;
XAllowEvents (display_info->dpy, AsyncKeyboard, ev->time);
clientToggleMaximized (c, WIN_STATE_MAXIMIZED_VERT, TRUE);
break;
case KEY_MAXIMIZE_HORIZ:
handled = TRUE;
XAllowEvents (display_info->dpy, AsyncKeyboard, ev->time);
clientToggleMaximized (c, WIN_STATE_MAXIMIZED_HORIZ, TRUE);
break;
case KEY_SHADE_WINDOW:
handled = TRUE;
XAllowEvents (display_info->dpy, AsyncKeyboard, ev->time);
clientToggleShaded (c);
break;
case KEY_STICK_WINDOW:
handled = TRUE;
XAllowEvents (display_info->dpy, AsyncKeyboard, ev->time);
if (FLAG_TEST(c->xfwm_flags, XFWM_FLAG_HAS_STICK))
{
clientToggleSticky (c, TRUE);
Olivier Fourdan
committed
}
handled = TRUE;
XAllowEvents (display_info->dpy, AsyncKeyboard, ev->time);
Olivier Fourdan
committed
clientRaise (c, None);
handled = TRUE;
XAllowEvents (display_info->dpy, AsyncKeyboard, ev->time);
Olivier Fourdan
committed
clientLower (c, None);
handled = TRUE;
XAllowEvents (display_info->dpy, AsyncKeyboard, ev->time);
Olivier Fourdan
committed
clientToggleLayerAbove (c);
case KEY_TOGGLE_FULLSCREEN:
handled = TRUE;
XAllowEvents (display_info->dpy, AsyncKeyboard, ev->time);
clientToggleFullscreen (c);
break;
case KEY_MOVE_NEXT_WORKSPACE:
handled = TRUE;
XAllowEvents (display_info->dpy, AsyncKeyboard, ev->time);
Olivier Fourdan
committed
workspaceSwitch (screen_info, screen_info->current_ws + 1, c, TRUE, ev->time);
break;
case KEY_MOVE_PREV_WORKSPACE:
handled = TRUE;
XAllowEvents (display_info->dpy, AsyncKeyboard, ev->time);
Olivier Fourdan
committed
workspaceSwitch (screen_info, screen_info->current_ws - 1, c, TRUE, ev->time);
Olivier Fourdan
committed
case KEY_MOVE_UP_WORKSPACE:
handled = TRUE;
XAllowEvents (display_info->dpy, AsyncKeyboard, ev->time);
Olivier Fourdan
committed
workspaceMove (screen_info, -1, 0, c, ev->time);
Olivier Fourdan
committed
break;
case KEY_MOVE_DOWN_WORKSPACE:
handled = TRUE;
XAllowEvents (display_info->dpy, AsyncKeyboard, ev->time);
Olivier Fourdan
committed
workspaceMove (screen_info, 1, 0, c, ev->time);
Olivier Fourdan
committed
break;
case KEY_MOVE_LEFT_WORKSPACE:
handled = TRUE;
XAllowEvents (display_info->dpy, AsyncKeyboard, ev->time);
Olivier Fourdan
committed
workspaceMove (screen_info, 0, -1, c, ev->time);
Olivier Fourdan
committed
break;
case KEY_MOVE_RIGHT_WORKSPACE:
handled = TRUE;
XAllowEvents (display_info->dpy, AsyncKeyboard, ev->time);
Olivier Fourdan
committed
workspaceMove (screen_info, 0, 1, c, ev->time);
Olivier Fourdan
committed
break;
case KEY_MOVE_WORKSPACE_1:
case KEY_MOVE_WORKSPACE_2:
case KEY_MOVE_WORKSPACE_3:
case KEY_MOVE_WORKSPACE_4:
case KEY_MOVE_WORKSPACE_5:
case KEY_MOVE_WORKSPACE_6:
case KEY_MOVE_WORKSPACE_7:
case KEY_MOVE_WORKSPACE_8:
case KEY_MOVE_WORKSPACE_9:
case KEY_MOVE_WORKSPACE_10:
case KEY_MOVE_WORKSPACE_11:
case KEY_MOVE_WORKSPACE_12:
handled = TRUE;
XAllowEvents (display_info->dpy, AsyncKeyboard, ev->time);
if ((guint) (key - KEY_MOVE_WORKSPACE_1) < screen_info->workspace_count)
Olivier Fourdan
committed
{
clientRaise (c, None);
Olivier Fourdan
committed
workspaceSwitch (screen_info, key - KEY_MOVE_WORKSPACE_1, c, TRUE, ev->time);
Olivier Fourdan
committed
}
Olivier Fourdan
committed
case KEY_POPUP_MENU:
handled = TRUE;
XAllowEvents (display_info->dpy, AsyncKeyboard, ev->time);
show_window_menu (c, frameX (c) + frameLeft (c),
frameY (c) + frameTop (c),
Button1, ev->time);
Olivier Fourdan
committed
break;
case KEY_FILL_WINDOW:
handled = TRUE;
XAllowEvents (display_info->dpy, AsyncKeyboard, ev->time);
clientFill (c, CLIENT_FILL);
break;
case KEY_FILL_VERT:
handled = TRUE;
XAllowEvents (display_info->dpy, AsyncKeyboard, ev->time);
clientFill (c, CLIENT_FILL_VERT);
break;
case KEY_FILL_HORIZ:
handled = TRUE;
XAllowEvents (display_info->dpy, AsyncKeyboard, ev->time);
clientFill (c, CLIENT_FILL_HORIZ);
break;
default:
break;
}
Olivier Fourdan
committed
}
else
{
key = myScreenGetKeyPressed (ev_screen_info, ev);
switch (key)
{
case KEY_CYCLE_WINDOWS:
status = EVENT_FILTER_REMOVE;
handled = TRUE;
XAllowEvents (display_info->dpy, AsyncKeyboard, ev->time);
if (ev_screen_info->clients)
Olivier Fourdan
committed
clientCycle (ev_screen_info->clients->prev, ev);
Olivier Fourdan
committed
case KEY_CLOSE_WINDOW:
status = EVENT_FILTER_REMOVE;
handled = TRUE;
XAllowEvents (display_info->dpy, AsyncKeyboard, ev->time);
Olivier Fourdan
committed
if (display_info->session)
{
logout_session (display_info->session);
}
break;
default:
break;
}
Olivier Fourdan
committed
}
Olivier Fourdan
committed
switch (key)
{
Olivier Fourdan
committed
case KEY_SWITCH_WINDOW:
handled = TRUE;
XAllowEvents (display_info->dpy, AsyncKeyboard, ev->time);
clientSwitchWindow ();
break;
case KEY_SWITCH_APPLICATION:
handled = TRUE;
XAllowEvents (display_info->dpy, AsyncKeyboard, ev->time);
clientSwitchApp ();
break;
case KEY_NEXT_WORKSPACE:
status = EVENT_FILTER_REMOVE;
handled = TRUE;
XAllowEvents (display_info->dpy, AsyncKeyboard, ev->time);
workspaceSwitch (ev_screen_info, ev_screen_info->current_ws + 1, NULL, TRUE, ev->time);
break;
case KEY_PREV_WORKSPACE:
status = EVENT_FILTER_REMOVE;
handled = TRUE;
XAllowEvents (display_info->dpy, AsyncKeyboard, ev->time);
workspaceSwitch (ev_screen_info, ev_screen_info->current_ws - 1, NULL, TRUE, ev->time);
Olivier Fourdan
committed
case KEY_UP_WORKSPACE:
status = EVENT_FILTER_REMOVE;
handled = TRUE;
XAllowEvents (display_info->dpy, AsyncKeyboard, ev->time);
workspaceMove(ev_screen_info, -1, 0, NULL, ev->time);
Olivier Fourdan
committed
break;
case KEY_DOWN_WORKSPACE:
status = EVENT_FILTER_REMOVE;
handled = TRUE;
XAllowEvents (display_info->dpy, AsyncKeyboard, ev->time);
workspaceMove(ev_screen_info, 1, 0, NULL, ev->time);
Olivier Fourdan
committed
break;
case KEY_LEFT_WORKSPACE:
status = EVENT_FILTER_REMOVE;
handled = TRUE;
XAllowEvents (display_info->dpy, AsyncKeyboard, ev->time);
workspaceMove(ev_screen_info, 0, -1, NULL, ev->time);
Olivier Fourdan
committed
break;
case KEY_RIGHT_WORKSPACE:
status = EVENT_FILTER_REMOVE;
handled = TRUE;
XAllowEvents (display_info->dpy, AsyncKeyboard, ev->time);
workspaceMove(ev_screen_info, 0, 1, NULL, ev->time);
Olivier Fourdan
committed
break;
case KEY_ADD_WORKSPACE:
status = EVENT_FILTER_REMOVE;
handled = TRUE;
XAllowEvents (display_info->dpy, AsyncKeyboard, ev->time);
workspaceSetCount (ev_screen_info, ev_screen_info->workspace_count + 1);
break;
case KEY_DEL_WORKSPACE:
status = EVENT_FILTER_REMOVE;
handled = TRUE;
XAllowEvents (display_info->dpy, AsyncKeyboard, ev->time);
workspaceSetCount (ev_screen_info, ev_screen_info->workspace_count - 1);
Olivier Fourdan
committed
case KEY_ADD_ADJACENT_WORKSPACE:
XAllowEvents (display_info->dpy, AsyncKeyboard, ev->time);
handled = TRUE;
Olivier Fourdan
committed
workspaceInsert (ev_screen_info, ev_screen_info->current_ws + 1);
break;
case KEY_DEL_ACTIVE_WORKSPACE:
XAllowEvents (display_info->dpy, AsyncKeyboard, ev->time);
handled = TRUE;
Olivier Fourdan
committed
workspaceDelete (ev_screen_info, ev_screen_info->current_ws);
break;
case KEY_WORKSPACE_1:
case KEY_WORKSPACE_2:
case KEY_WORKSPACE_3:
case KEY_WORKSPACE_4:
case KEY_WORKSPACE_5:
case KEY_WORKSPACE_6:
case KEY_WORKSPACE_7:
case KEY_WORKSPACE_8:
case KEY_WORKSPACE_9:
case KEY_WORKSPACE_10:
case KEY_WORKSPACE_11:
case KEY_WORKSPACE_12:
status = EVENT_FILTER_REMOVE;
handled = TRUE;
XAllowEvents (display_info->dpy, AsyncKeyboard, ev->time);
if ((guint) (key - KEY_WORKSPACE_1) < ev_screen_info->workspace_count)
Olivier Fourdan
committed
{
workspaceSwitch (ev_screen_info, key - KEY_WORKSPACE_1, NULL, TRUE, ev->time);
Olivier Fourdan
committed
}
case KEY_SHOW_DESKTOP:
status = EVENT_FILTER_REMOVE;
handled = TRUE;
XAllowEvents (display_info->dpy, AsyncKeyboard, ev->time);
toggle_show_desktop (ev_screen_info);
default:
break;
if (!handled)
{
/* That should not happen, really */
g_warning ("Unhandled keyboard shortcut");
XAllowEvents (display_info->dpy, AsyncKeyboard, CurrentTime);
}
return status;
Olivier Fourdan
committed
static eventFilterStatus
handleKeyRelease (DisplayInfo *display_info, XKeyEvent * ev)
{
TRACE ("entering handleKeyRelease");
Olivier Fourdan
committed
return EVENT_FILTER_PASS;
}
/* User has clicked on an edge or corner.
* Button 1 : Raise and resize
* Button 2 : Move
* Button 3 : Resize
*/
edgeButton (Client * c, int part, XButtonEvent * ev)
Olivier Fourdan
committed
ScreenInfo *screen_info;
Olivier Fourdan
committed
screen_info = c->screen_info;
state = ev->state & MODIFIER_MASK;
if (ev->button == Button2)
XfwmButtonClickType tclick;
Olivier Fourdan
committed
Olivier Fourdan
committed
tclick = typeOfClick (screen_info, c->window, (XEvent *) ev, FALSE);
if (tclick == XFWM_BUTTON_CLICK)
{
Olivier Fourdan
committed
clientLower (c, None);
Olivier Fourdan
committed
else if (tclick != XFWM_BUTTON_UNDEFINED)
Olivier Fourdan
committed
else if ((ev->button == Button1) || (ev->button == Button3))
Olivier Fourdan
committed
if ((ev->button == Button1) ||
((screen_info->params->easy_click) && (state == screen_info->params->easy_click)))
if (!(c->type & WINDOW_TYPE_DONT_FOCUS))
{
Olivier Fourdan
committed
clientSetFocus (screen_info, c, ev->time, NO_FOCUS_FLAG);
}
Olivier Fourdan
committed
clientRaise (c, None);
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
edgeGetPart (Client *c, XButtonEvent * ev)
{
int part, x_corner_pixels, y_corner_pixels, x_distance, y_distance;
/* Corner is 1/3 of the side */
x_corner_pixels = MAX(c->width / 3, 50);
y_corner_pixels = MAX(c->height / 3, 50);
/* Distance from event to edge of client window */
x_distance = c->width / 2 - abs(c->width / 2 - ev->x);
y_distance = c->height / 2 - abs(c->height / 2 - ev->y);
/* Set a sensible default value */
part = CORNER_BOTTOM_RIGHT;
if (x_distance < x_corner_pixels && y_distance < y_corner_pixels)
{
/* In a corner */
if (ev->x < c->width / 2)
{
if (ev->y < c->height / 2)
{
part = CORNER_TOP_LEFT;
}
else
{
part = CORNER_BOTTOM_LEFT;
}
}
else
{
if (ev->y < c->height / 2)
{
part = CORNER_TOP_RIGHT;
}
else
{
part = CORNER_BOTTOM_RIGHT;
}
}
}
else
{
/* Not a corner - some side */
if (x_distance / x_corner_pixels < y_distance / y_corner_pixels)
{
/* Left or right side */
if (ev->x < c->width / 2)
{
part = CORNER_COUNT + SIDE_LEFT;
}
else
{
part = CORNER_COUNT + SIDE_RIGHT;
}
}
else
{
/* Top or bottom side */
if (ev->y < c->height / 2)
{
part = CORNER_COUNT + SIDE_TOP;
}
else
{
part = CORNER_COUNT + SIDE_BOTTOM;
}
}
}
return part;
}
button1Action (Client * c, XButtonEvent * ev)
XfwmButtonClickType tclick;
g_return_if_fail (c != NULL);
g_return_if_fail (ev != NULL);
screen_info = c->screen_info;
display_info = screen_info->display_info;
if (!(c->type & WINDOW_TYPE_DONT_FOCUS))
{
clientSetFocus (screen_info, c, ev->time, NO_FOCUS_FLAG);
}
Olivier Fourdan
committed
clientRaise (c, None);
Olivier Fourdan
committed
tclick = typeOfClick (screen_info, c->window, ©_event, TRUE);
if ((tclick == XFWM_BUTTON_DRAG)
|| (tclick == XFWM_BUTTON_CLICK_AND_DRAG))
else if (tclick == XFWM_BUTTON_DOUBLE_CLICK)
switch (screen_info->params->double_click_action)
Olivier Fourdan
committed
case DBL_CLICK_ACTION_MAXIMIZE:
clientToggleMaximized (c, WIN_STATE_MAXIMIZED, TRUE);
Olivier Fourdan
committed
case DBL_CLICK_ACTION_SHADE:
clientToggleShaded (c);
break;
case DBL_CLICK_ACTION_FILL:
clientFill(c, CLIENT_FILL);
break;
Olivier Fourdan
committed
case DBL_CLICK_ACTION_HIDE:
if (CLIENT_CAN_HIDE_WINDOW (c))
{
Olivier Fourdan
committed
clientWithdraw (c, c->win_workspace, TRUE);
default:
break;
titleButton (Client * c, guint state, XButtonEvent * ev)
g_return_if_fail (c != NULL);
g_return_if_fail (ev != NULL);
/* Get Screen data from the client itself */
screen_info = c->screen_info;
display_info = screen_info->display_info;
if (ev->button == Button1)
{
button1Action (c, ev);
}
else if (ev->button == Button2)
{
Olivier Fourdan
committed
clientLower (c, None);
}
else if (ev->button == Button3)
{
/*
We need to copy the event to keep the original event untouched
for gtk to handle it (in case we open up the menu)
*/
XfwmButtonClickType tclick;
memcpy(©_event, ev, sizeof(XEvent));
Olivier Fourdan
committed
tclick = typeOfClick (screen_info, c->window, ©_event, FALSE);
if (tclick == XFWM_BUTTON_DRAG)
{
Olivier Fourdan
committed
else if (tclick != XFWM_BUTTON_UNDEFINED)
if (!(c->type & WINDOW_TYPE_DONT_FOCUS))
{
clientSetFocus (screen_info, c, ev->time, NO_FOCUS_FLAG);
}
Olivier Fourdan
committed
clientRaise (c, None);
}
ev->window = ev->root;
g_signal_handler_disconnect (GTK_OBJECT (myScreenGetGtkWidget (screen_info)), screen_info->button_handler_id);
screen_info->button_handler_id = g_signal_connect (GTK_OBJECT (myScreenGetGtkWidget (screen_info)),
"button_press_event", GTK_SIGNAL_FUNC (show_popup_cb), (gpointer) c);
/* Let GTK handle this for us. */
}
}
else if (ev->button == Button4)
{
/* Mouse wheel scroll up */
if (state == AltMask)
{
clientIncOpacity(c);
}
else if (!FLAG_TEST (c->flags, CLIENT_FLAG_SHADED))
{
clientShade (c);
}
else if (ev->button == Button5)
/* Mouse wheel scroll down */
if (state == AltMask)
{
clientDecOpacity(c);
}
else if (FLAG_TEST (c->flags, CLIENT_FLAG_SHADED))
{
clientUnshade (c);
}
else if (ev->button == Button6)
{
/* Mouse wheel scroll left, or left side button */
clientDecOpacity(c);
}
else if (ev->button == Button7)
{
/* Mouse wheel scroll right, or right side button */
clientIncOpacity(c);
}
rootScrollButton (DisplayInfo *display_info, XButtonEvent * ev)
static guint32 lastscroll = CurrentTime;
Olivier Fourdan
committed
if ((ev->time - lastscroll) < 25) /* ms */
/* Too many events in too little time, drop this event... */
return;
}
lastscroll = ev->time;
/* Get the screen structure from the root of the event */
screen_info = myDisplayGetScreenFromRoot (display_info, ev->root);
if (!screen_info)
{
return;
}
if (ev->button == Button4)
{
Olivier Fourdan
committed
workspaceSwitch (screen_info, screen_info->current_ws - 1, NULL, TRUE, ev->time);
}
else if (ev->button == Button5)
{
Olivier Fourdan
committed
workspaceSwitch (screen_info, screen_info->current_ws + 1, NULL, TRUE, ev->time);
}
}
static eventFilterStatus
handleButtonPress (DisplayInfo *display_info, XButtonEvent * ev)
TRACE ("entering handleButtonPress");
c = myDisplayGetClientFromWindow (display_info, ev->window, SEARCH_FRAME | SEARCH_WINDOW);
win = ev->subwindow;
Olivier Fourdan
committed
if ((ev->button == Button1) && (state) && (state == screen_info->params->easy_click))
{
button1Action (c, ev);
}
Olivier Fourdan
committed
else if ((ev->button == Button2) && (state) && (state == screen_info->params->easy_click))
Olivier Fourdan
committed
clientLower (c, None);
Olivier Fourdan
committed
else if ((ev->button == Button3) && (state) && (state == screen_info->params->easy_click))
Olivier Fourdan
committed
edgeButton (c, part, ev);
Olivier Fourdan
committed
#if 0 /* Binding the alt+scroll wheel to switch app/window is not handy, disabling for now */
else if ((ev->button == Button4) && (state) && (state == screen_info->params->easy_click))
{
clientSwitchWindow ();
}
else if ((ev->button == Button5) && (state) && (state == screen_info->params->easy_click))
{
clientSwitchApp ();
}
#endif
else if (WIN_IS_BUTTON (win))
{
if (ev->button <= Button3)
{
if (!(c->type & WINDOW_TYPE_DONT_FOCUS))
{
clientSetFocus (screen_info, c, ev->time, NO_FOCUS_FLAG);
}
Olivier Fourdan
committed
clientRaise (c, None);
}
clientButtonPress (c, win, ev);
}
}
else if (win == MYWINDOW_XWINDOW (c->title))
{
titleButton (c, state, ev);
}
else if (win == MYWINDOW_XWINDOW (c->buttons[MENU_BUTTON]))
{
if (ev->button == Button1)
{
/*
We need to copy the event to keep the original event untouched
for gtk to handle it (in case we open up the menu)
*/
XfwmButtonClickType tclick;
Olivier Fourdan
committed
tclick = typeOfClick (screen_info, c->window, ©_event, TRUE);
if (tclick == XFWM_BUTTON_DOUBLE_CLICK)
{
clientClose (c);
}
Olivier Fourdan
committed
else if (tclick != XFWM_BUTTON_UNDEFINED)
if (!(c->type & WINDOW_TYPE_DONT_FOCUS))
{
clientSetFocus (screen_info, c, ev->time, NO_FOCUS_FLAG);
}