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>
Stephan Arts
committed
#include <libxfce4ui/libxfce4ui.h>
#include <common/xfwm-common.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"
#include "display.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 DOUBLE_CLICK_GRAB (ButtonMotionMask | \
PointerMotionMask | \
ButtonPressMask | \
ButtonReleaseMask)
Olivier Fourdan
committed
/* Forward decl. */
static eventFilterStatus handleEvent (DisplayInfo *display_info,
XfwmEvent *event);
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,
static gboolean show_popup_cb (GtkWidget * widget,
GdkEventButton * ev,
gpointer data);
static gboolean set_reload (DisplayInfo *display_info);
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
guint timeout;
gint x0;
gint y0;
guint t0;
gint xcurrent;
gint ycurrent;
guint tcurrent;
gint double_click_time;
gint double_click_distance;
Olivier Fourdan
committed
};
Olivier Fourdan
committed
static gboolean
typeOfClick_end (gpointer data)
{
XfwmButtonClickData *passdata;
Olivier Fourdan
committed
if (passdata->timeout)
{
g_source_remove (passdata->timeout);
passdata->timeout = 0;
}
gtk_main_quit ();
Olivier Fourdan
committed
}
typeOfClick_event_filter (XfwmEvent *event, gpointer data)
Olivier Fourdan
committed
{
XfwmButtonClickData *passdata;
eventFilterStatus status;
Olivier Fourdan
committed
status = EVENT_FILTER_CONTINUE;
timestamp = myDisplayUpdateCurrentTime (passdata->display_info, event);
Olivier Fourdan
committed
Olivier Fourdan
committed
{
Olivier Fourdan
committed
if (((gint) passdata->tcurrent - (gint) passdata->t0) > passdata->double_click_time)
{
keep_going = FALSE;
}
}
if (event->meta.type == XFWM_EVENT_BUTTON)
Olivier Fourdan
committed
{
if (event->button.button == passdata->button)
Olivier Fourdan
committed
{
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;
}
Olivier Fourdan
committed
status = EVENT_FILTER_STOP;
Olivier Fourdan
committed
}
else if (event->meta.type == XFWM_EVENT_MOTION)
Olivier Fourdan
committed
{
passdata->xcurrent = event->motion.x_root;
passdata->ycurrent = event->motion.y_root;
Olivier Fourdan
committed
if ((ABS (passdata->x0 - passdata->xcurrent) > passdata->double_click_distance) ||
(ABS (passdata->y0 - passdata->ycurrent) > passdata->double_click_distance))
{
keep_going = FALSE;
}
status = EVENT_FILTER_STOP;
Olivier Fourdan
committed
}
else if ((event->meta.xevent->type == DestroyNotify) || (event->meta.xevent->type == UnmapNotify))
Olivier Fourdan
committed
{
if (event->meta.window == passdata->w)
Olivier Fourdan
committed
{
/* Discard, mark the click as undefined */
passdata->clicks = (guint) XFWM_BUTTON_UNDEFINED;
keep_going = FALSE;
}
}
Olivier Fourdan
committed
if (!keep_going)
Olivier Fourdan
committed
{
TRACE ("click type=%u", passdata->clicks);
TRACE ("time=%ims (timeout=%ims)", (gint) passdata->tcurrent - (gint) passdata->t0, passdata->double_click_time);
TRACE ("dist x=%i (max=%i)", ABS (passdata->x0 - passdata->xcurrent), passdata->double_click_distance);
TRACE ("dist y=%i (max=%i)", ABS (passdata->y0 - passdata->ycurrent), passdata->double_click_distance);
Olivier Fourdan
committed
typeOfClick_end (data);
Olivier Fourdan
committed
}
return status;
}
typeOfClick (ScreenInfo *screen_info, Window w, XfwmEventButton *event, 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 (event != NULL, XFWM_BUTTON_UNDEFINED);
g_return_val_if_fail (w != None, XFWM_BUTTON_UNDEFINED);
display_info = screen_info->display_info;
g = myScreenGrabPointer (screen_info, FALSE, DOUBLE_CLICK_GRAB, None, event->time);
Olivier Fourdan
committed
if (!g)
{
gdk_display_beep (display_info->gdisplay);
myScreenUngrabPointer (screen_info, event->time);
Olivier Fourdan
committed
return XFWM_BUTTON_UNDEFINED;
}
passdata.display_info = display_info;
passdata.button = event->button;
Olivier Fourdan
committed
passdata.w = w;
passdata.x0 = event->x_root;
passdata.y0 = event->y_root;
passdata.t0 = event->time;
passdata.xcurrent = passdata.x0;
passdata.ycurrent = passdata.y0;
passdata.tcurrent = passdata.t0;
Olivier Fourdan
committed
passdata.clicks = 1;
passdata.allow_double_click = allow_double_click;
passdata.double_click_time = display_info->double_click_time;
passdata.double_click_distance = display_info->double_click_distance;
TRACE ("double click time= %i, distance=%i\n", display_info->double_click_time,
display_info->double_click_distance);
Olivier Fourdan
committed
passdata.timeout = g_timeout_add_full (G_PRIORITY_HIGH,
display_info->double_click_time,
Olivier Fourdan
committed
eventFilterPush (display_info->xfilter, typeOfClick_event_filter, &passdata);
Olivier Fourdan
committed
gtk_main ();
eventFilterPop (display_info->xfilter);
Olivier Fourdan
committed
Olivier Fourdan
committed
myScreenUngrabPointer (screen_info, myDisplayGetCurrentTime (display_info));
Olivier Fourdan
committed
return (XfwmButtonClickType) passdata.clicks;
Olivier Fourdan
committed
}
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, XfwmEventMotion *event)
Olivier Fourdan
committed
{
return EVENT_FILTER_REMOVE;
Olivier Fourdan
committed
}
static eventFilterStatus
handleKeyPress (DisplayInfo *display_info, XfwmEventKey *event)
eventFilterStatus status;
ScreenInfo *ev_screen_info;
ev_screen_info = myDisplayGetScreenFromRoot (display_info, event->root);
if (!ev_screen_info)
{
}
key = myScreenGetKeyPressed (screen_info, event);
status = EVENT_FILTER_REMOVE;
Olivier Fourdan
committed
switch (key)
{
clientMove (c, NULL);
clientResize (c, CORNER_BOTTOM_RIGHT, NULL);
break;
case KEY_CYCLE_WINDOWS:
case KEY_CYCLE_REVERSE_WINDOWS:
clientCycle (c, event);
break;
case KEY_CLOSE_WINDOW:
clientClose (c);
break;
case KEY_HIDE_WINDOW:
Olivier Fourdan
committed
clientWithdraw (c, c->win_workspace, TRUE);
break;
case KEY_MAXIMIZE_WINDOW:
clientToggleMaximized (c, CLIENT_FLAG_MAXIMIZED, TRUE);
break;
case KEY_MAXIMIZE_VERT:
clientToggleMaximized (c, CLIENT_FLAG_MAXIMIZED_VERT, TRUE);
break;
case KEY_MAXIMIZE_HORIZ:
clientToggleMaximized (c, CLIENT_FLAG_MAXIMIZED_HORIZ, TRUE);
break;
case KEY_SHADE_WINDOW:
clientToggleShaded (c);
break;
case KEY_STICK_WINDOW:
if (FLAG_TEST(c->xfwm_flags, XFWM_FLAG_HAS_STICK))
{
clientToggleSticky (c, TRUE);
Olivier Fourdan
committed
}
Olivier Fourdan
committed
clientRaise (c, None);
Olivier Fourdan
committed
clientLower (c, None);
case KEY_RAISELOWER_WINDOW:
if (clientIsTopMost (c))
{
clientLower (c, None);
}
else
{
clientRaise (c, None);
}
break;
Olivier Fourdan
committed
clientToggleLayerAbove (c);
case KEY_TOGGLE_FULLSCREEN:
clientToggleFullscreen (c);
break;
case KEY_MOVE_TO_MONITOR_DOWN:
case KEY_MOVE_TO_MONITOR_LEFT:
case KEY_MOVE_TO_MONITOR_RIGHT:
case KEY_MOVE_TO_MONITOR_UP:
clientMoveToMonitorByDirection (c, key);
break;
case KEY_MOVE_NEXT_WORKSPACE:
workspaceSwitch (screen_info, screen_info->current_ws + 1, c, TRUE, event->time);
break;
case KEY_MOVE_PREV_WORKSPACE:
workspaceSwitch (screen_info, screen_info->current_ws - 1, c, TRUE, event->time);
Olivier Fourdan
committed
case KEY_MOVE_UP_WORKSPACE:
workspaceMove (screen_info, -1, 0, c, event->time);
Olivier Fourdan
committed
break;
case KEY_MOVE_DOWN_WORKSPACE:
workspaceMove (screen_info, 1, 0, c, event->time);
Olivier Fourdan
committed
break;
case KEY_MOVE_LEFT_WORKSPACE:
workspaceMove (screen_info, 0, -1, c, event->time);
Olivier Fourdan
committed
break;
case KEY_MOVE_RIGHT_WORKSPACE:
workspaceMove (screen_info, 0, 1, c, event->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:
if ((guint) (key - KEY_MOVE_WORKSPACE_1) < screen_info->workspace_count)
Olivier Fourdan
committed
{
clientRaise (c, None);
clientSetWorkspace (c, key - KEY_MOVE_WORKSPACE_1, TRUE);
Olivier Fourdan
committed
}
Olivier Fourdan
committed
case KEY_POPUP_MENU:
show_window_menu (c, frameExtentX (c) + frameLeft (c),
frameExtentY (c) + frameTop (c),
Olivier Fourdan
committed
break;
case KEY_FILL_WINDOW:
clientFill (c, CLIENT_FILL);
break;
case KEY_FILL_VERT:
clientFill (c, CLIENT_FILL_VERT);
break;
case KEY_FILL_HORIZ:
clientFill (c, CLIENT_FILL_HORIZ);
break;
case KEY_TILE_DOWN:
clientToggleTile (c, TILE_DOWN);
break;
clientToggleTile (c, TILE_LEFT);
break;
clientToggleTile (c, TILE_RIGHT);
break;
break;
clientToggleTile (c, TILE_DOWN_LEFT);
clientToggleTile (c, TILE_DOWN_RIGHT);
clientToggleTile (c, TILE_UP_LEFT);
clientToggleTile (c, TILE_UP_RIGHT);
default:
break;
}
Olivier Fourdan
committed
}
else
{
key = myScreenGetKeyPressed (ev_screen_info, event);
switch (key)
{
case KEY_CYCLE_WINDOWS:
status = EVENT_FILTER_REMOVE;
if (ev_screen_info->clients)
clientCycle (ev_screen_info->clients->prev, event);
Olivier Fourdan
committed
case KEY_CLOSE_WINDOW:
status = EVENT_FILTER_REMOVE;
Olivier Fourdan
committed
if (display_info->session)
{
Stephan Arts
committed
xfce_sm_client_request_shutdown(display_info->session, XFCE_SM_CLIENT_SHUTDOWN_HINT_LOGOUT);
Olivier Fourdan
committed
}
break;
default:
break;
}
Olivier Fourdan
committed
}
Olivier Fourdan
committed
switch (key)
{
Olivier Fourdan
committed
case KEY_SWITCH_WINDOW:
clientSwitchWindow ();
break;
case KEY_SWITCH_APPLICATION:
clientSwitchApp ();
break;
case KEY_NEXT_WORKSPACE:
status = EVENT_FILTER_REMOVE;
workspaceSwitch (ev_screen_info, ev_screen_info->current_ws + 1, NULL, TRUE, event->time);
break;
case KEY_PREV_WORKSPACE:
status = EVENT_FILTER_REMOVE;
workspaceSwitch (ev_screen_info, ev_screen_info->current_ws - 1, NULL, TRUE, event->time);
Olivier Fourdan
committed
case KEY_UP_WORKSPACE:
status = EVENT_FILTER_REMOVE;
workspaceMove(ev_screen_info, -1, 0, NULL, event->time);
Olivier Fourdan
committed
break;
case KEY_DOWN_WORKSPACE:
status = EVENT_FILTER_REMOVE;
workspaceMove(ev_screen_info, 1, 0, NULL, event->time);
Olivier Fourdan
committed
break;
case KEY_LEFT_WORKSPACE:
status = EVENT_FILTER_REMOVE;
workspaceMove(ev_screen_info, 0, -1, NULL, event->time);
Olivier Fourdan
committed
break;
case KEY_RIGHT_WORKSPACE:
status = EVENT_FILTER_REMOVE;
workspaceMove(ev_screen_info, 0, 1, NULL, event->time);
Olivier Fourdan
committed
break;
case KEY_ADD_WORKSPACE:
status = EVENT_FILTER_REMOVE;
workspaceSetCount (ev_screen_info, ev_screen_info->workspace_count + 1);
break;
case KEY_DEL_WORKSPACE:
status = EVENT_FILTER_REMOVE;
workspaceSetCount (ev_screen_info, ev_screen_info->workspace_count - 1);
Olivier Fourdan
committed
case KEY_ADD_ADJACENT_WORKSPACE:
workspaceInsert (ev_screen_info, ev_screen_info->current_ws + 1);
break;
case KEY_DEL_ACTIVE_WORKSPACE:
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;
if ((guint) (key - KEY_WORKSPACE_1) < ev_screen_info->workspace_count)
Olivier Fourdan
committed
{
workspaceSwitch (ev_screen_info, key - KEY_WORKSPACE_1, NULL, TRUE, event->time);
Olivier Fourdan
committed
}
case KEY_SHOW_DESKTOP:
status = EVENT_FILTER_REMOVE;
toggle_show_desktop (ev_screen_info);
default:
break;
Olivier Fourdan
committed
/* Release pending events */
XAllowEvents (display_info->dpy, SyncKeyboard, CurrentTime);
return status;
Olivier Fourdan
committed
static eventFilterStatus
handleKeyRelease (DisplayInfo *display_info, XfwmEventKey *event)
Olivier Fourdan
committed
{
Olivier Fourdan
committed
/* Release pending events */
XAllowEvents (display_info->dpy, SyncKeyboard, CurrentTime);
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, XfwmEventButton *event)
Olivier Fourdan
committed
ScreenInfo *screen_info;
XfwmButtonClickType tclick;
Olivier Fourdan
committed
screen_info = c->screen_info;
state = event->state & MODIFIER_MASK;
Olivier Fourdan
committed
if (event->button == Button2)
tclick = typeOfClick (screen_info, c->window, event, FALSE);
if (tclick == XFWM_BUTTON_CLICK)
{
Olivier Fourdan
committed
clientLower (c, None);
clientMove (c, event);
else if ((event->button == Button1) || (event->button == Button3))
if ((event->button == Button1) ||
Olivier Fourdan
committed
((screen_info->params->easy_click) && (state == screen_info->params->easy_click)))
if (!(c->type & WINDOW_TYPE_DONT_FOCUS))
{
clientSetFocus (screen_info, c, event->time, NO_FOCUS_FLAG);
}
Olivier Fourdan
committed
clientRaise (c, None);
tclick = typeOfClick (screen_info, c->window, event, TRUE);
if (tclick == XFWM_BUTTON_DOUBLE_CLICK)
{
switch (part)
{
case CORNER_COUNT + SIDE_LEFT:
case CORNER_COUNT + SIDE_RIGHT:
clientFill(c, CLIENT_FILL_HORIZ);
break;
case CORNER_COUNT + SIDE_TOP:
case CORNER_COUNT + SIDE_BOTTOM:
clientFill(c, CLIENT_FILL_VERT);
break;
default:
clientFill(c, CLIENT_FILL);
break;
}
}
clientResize (c, part, event);
edgeGetPart (Client *c, XfwmEventButton *event)
{
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 - event->x);
y_distance = c->height / 2 - abs(c->height / 2 - event->y);
if (x_distance < x_corner_pixels && y_distance < y_corner_pixels)
{
/* In a corner */
if (event->x < c->width / 2)
if (event->y < c->height / 2)
{
part = CORNER_TOP_LEFT;
}
else
{
part = CORNER_BOTTOM_LEFT;
}
}
else
{
if (event->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 (event->x < c->width / 2)
{
part = CORNER_COUNT + SIDE_LEFT;
}
else
{
part = CORNER_COUNT + SIDE_RIGHT;
}
}
else
{
/* Top or bottom side */
if (event->y < c->height / 2)
{
part = CORNER_COUNT + SIDE_TOP;
}
else
{
part = CORNER_COUNT + SIDE_BOTTOM;
}
}
}
return part;
}
button1Action (Client *c, XfwmEventButton *event)
XfwmButtonClickType tclick;
g_return_if_fail (c != NULL);
g_return_if_fail (event != NULL);
if (!(c->type & WINDOW_TYPE_DONT_FOCUS))
{
clientSetFocus (screen_info, c, event->time, NO_FOCUS_FLAG);
}
Olivier Fourdan
committed
clientRaise (c, None);
tclick = typeOfClick (screen_info, c->window, event, TRUE);
Olivier Fourdan
committed
if ((tclick == XFWM_BUTTON_DRAG) || (tclick == XFWM_BUTTON_CLICK_AND_DRAG))
clientMove (c, event);
else if (tclick == XFWM_BUTTON_DOUBLE_CLICK)
switch (screen_info->params->double_click_action)
case DOUBLE_CLICK_ACTION_MAXIMIZE:
clientToggleMaximized (c, CLIENT_FLAG_MAXIMIZED, TRUE);
case DOUBLE_CLICK_ACTION_SHADE:
clientToggleShaded (c);
break;
case DOUBLE_CLICK_ACTION_FILL:
clientFill(c, CLIENT_FILL);
break;
case DOUBLE_CLICK_ACTION_HIDE:
if (CLIENT_CAN_HIDE_WINDOW (c))
{
Olivier Fourdan
committed
clientWithdraw (c, c->win_workspace, TRUE);
case DOUBLE_CLICK_ACTION_ABOVE:
clientToggleLayerAbove (c);
break;
default:
break;
titleButton (Client *c, guint state, XfwmEventButton *event)
g_return_if_fail (c != NULL);
g_return_if_fail (event != NULL);
/* Get Screen data from the client itself */
if (event->button == Button1)
button1Action (c, event);
else if (event->button == Button2)
Olivier Fourdan
committed
clientLower (c, None);
else if (event->button == Button3)
XfwmButtonClickType tclick;
tclick = typeOfClick (screen_info, c->window, event, FALSE);
if (tclick == XFWM_BUTTON_DRAG)
{
clientMove (c, event);
Olivier Fourdan
committed
else if (tclick != XFWM_BUTTON_UNDEFINED)
if (!(c->type & WINDOW_TYPE_DONT_FOCUS))
{
clientSetFocus (screen_info, c, event->time, NO_FOCUS_FLAG);
}
Olivier Fourdan
committed
clientRaise (c, None);
xfwm_device_button_update_window (event, event->root);
g_signal_handler_disconnect (G_OBJECT (myScreenGetGtkWidget (screen_info)), screen_info->button_handler_id);
screen_info->button_handler_id = g_signal_connect (G_OBJECT (myScreenGetGtkWidget (screen_info)),
"button_press_event", G_CALLBACK (show_popup_cb), (gpointer) c);
/* Let GTK handle this for us. */
}
else if (event->button == Button4)
/* Mouse wheel scroll up */
if ((state) && (state == screen_info->params->easy_click) && compositorIsActive (screen_info))
else
#endif /* HAVE_COMPOSITOR */
if (!FLAG_TEST (c->flags, CLIENT_FLAG_SHADED))
if (screen_info->params->mousewheel_rollup)
{
clientShade (c);
}
else if (event->button == Button5)
/* Mouse wheel scroll down */
if ((state) && (state == screen_info->params->easy_click) && compositorIsActive (screen_info))
else
#endif /* HAVE_COMPOSITOR */
if (FLAG_TEST (c->flags, CLIENT_FLAG_SHADED))
if (screen_info->params->mousewheel_rollup)
{
clientUnshade (c);
}
#ifdef HAVE_COMPOSITOR
else if (screen_info->params->horiz_scroll_opacity)
if (event->button == Button6)
{
/* Mouse wheel scroll left, or left side button */
clientDecOpacity(c);
}
else if (event->button == Button7)
{
/* Mouse wheel scroll right, or right side button */
clientIncOpacity(c);
}
#endif /* HAVE_COMPOSITOR */
rootScrollButton (DisplayInfo *display_info, XfwmEventButton *event)
static guint32 lastscroll = CurrentTime;
if ((event->time - lastscroll) < 25) /* ms */
/* Too many events in too little time, drop this event... */
return;
lastscroll = event->time;
/* Get the screen structure from the root of the event */
screen_info = myDisplayGetScreenFromRoot (display_info, event->root);
if (!screen_info)
{
return;
}
if (event->button == Button4)
workspaceSwitch (screen_info, screen_info->current_ws - 1, NULL, TRUE, event->time);
else if (event->button == Button5)
workspaceSwitch (screen_info, screen_info->current_ws + 1, NULL, TRUE, event->time);
}
}
static eventFilterStatus
handleButtonPress (DisplayInfo *display_info, XfwmEventButton *event)
c = myDisplayGetClientFromWindow (display_info, event->meta.window,
SEARCH_FRAME | SEARCH_WINDOW);
state = event->state & MODIFIER_MASK;
win = event->subwindow;
if ((event->button == Button1) && (state) && (state == screen_info->params->easy_click))
button1Action (c, event);
else if ((event->button == Button2) && (state) && (state == screen_info->params->easy_click))
Olivier Fourdan
committed
clientLower (c, None);
else if ((event->button == Button3) && (state) && (state == screen_info->params->easy_click))
part = edgeGetPart (c, event);
edgeButton (c, part, event);
else if ((event->button == Button4) && (screen_info->params->zoom_desktop) && (state) &&
(state == screen_info->params->easy_click) && compositorIsActive (screen_info))
Olivier Fourdan
committed
{
compositorZoomIn(screen_info, event);
Olivier Fourdan
committed
}
else if ((event->button == Button5) && (screen_info->params->zoom_desktop) && (state) &&
(state == screen_info->params->easy_click) && compositorIsActive (screen_info))
Olivier Fourdan
committed
{
compositorZoomOut(screen_info, event);
Olivier Fourdan
committed
}
else if ((event->button == Button8) && (state) && (state == screen_info->params->easy_click))
workspaceSwitch (screen_info, screen_info->current_ws - 1, NULL, TRUE, event->time);
else if ((event->button == Button9) && (state) && (state == screen_info->params->easy_click))
workspaceSwitch (screen_info, screen_info->current_ws + 1, NULL, TRUE, event->time);
else if (WIN_IS_BUTTON (win))
{
if (event->button <= Button3)
if (!(c->type & WINDOW_TYPE_DONT_FOCUS))
{
clientSetFocus (screen_info, c, event->time, NO_FOCUS_FLAG);
}
Olivier Fourdan
committed
clientRaise (c, None);
clientButtonPress (c, win, event);
}
}
else if (win == MYWINDOW_XWINDOW (c->title))
{
titleButton (c, state, event);
}
else if (win == MYWINDOW_XWINDOW (c->buttons[MENU_BUTTON]))
{
if (event->button == Button1)
{
XfwmButtonClickType tclick;
tclick = typeOfClick (screen_info, c->window, event, TRUE);
Olivier Fourdan
committed
if (tclick == XFWM_BUTTON_DOUBLE_CLICK)
{
clientClose (c);
}
else if (tclick != XFWM_BUTTON_UNDEFINED)
if (!(c->type & WINDOW_TYPE_DONT_FOCUS))
{
clientSetFocus (screen_info, c, event->time, NO_FOCUS_FLAG);
}
Olivier Fourdan
committed
clientRaise (c, None);
xfwm_device_button_update_window (event, event->root);
g_signal_handler_disconnect (G_OBJECT (myScreenGetGtkWidget (screen_info)), screen_info->button_handler_id);
screen_info->button_handler_id = g_signal_connect (G_OBJECT (myScreenGetGtkWidget (screen_info)),
"button_press_event", G_CALLBACK (show_popup_cb), (gpointer) c);
/* Let GTK handle this for us. */
}
}