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.
xfwm4 - (c) 2002-2006 Olivier Fourdan
#include <config.h>
#include <string.h>
#include <sys/time.h>
#include <time.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 "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
#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)
#define MODIFIER_MASK (ShiftMask | \
ControlMask | \
AltMask | \
MetaMask | \
SuperMask | \
HyperMask)
static guint raise_timeout = 0;
static GdkAtom atom_rcfiles = GDK_NONE;
Olivier Fourdan
committed
static int edge_scroll_x = 0;
Olivier Fourdan
committed
static int edge_scroll_y = 0;
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
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;
Olivier Fourdan
committed
passdata.timeout = g_timeout_add_full (G_PRIORITY_DEFAULT,
display_info->dbl_click_time,
(GtkFunction) typeOfClick_break,
(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 Time last_button_time = (Time) 0;
Olivier Fourdan
committed
if (last_button_time > ev->time)
{
return FALSE;
}
last_button_time = ev->time;
return TRUE;
}
Olivier Fourdan
committed
#endif
clear_timeout (void)
if (raise_timeout)
g_source_remove (raise_timeout);
raise_timeout = 0;
raise_cb (gpointer data)
TRACE ("entering raise_cb");
clear_timeout ();
c = clientGetFocus ();
Olivier Fourdan
committed
clientRaise (c, None);
if (raise_timeout)
g_source_remove (raise_timeout);
Olivier Fourdan
committed
raise_timeout = g_timeout_add_full (G_PRIORITY_DEFAULT,
screen_info->params->raise_delay,
(GtkFunction) raise_cb,
NULL, NULL);
moveRequest (Client * c, XEvent * ev)
if (FLAG_TEST (c->xfwm_flags, XFWM_FLAG_HAS_MOVE)
&& !FLAG_TEST (c->flags, CLIENT_FLAG_FULLSCREEN))
clientMove (c, ev);
resizeRequest (Client * c, int corner, XEvent * ev)
if (!FLAG_TEST (c->flags, CLIENT_FLAG_FULLSCREEN))
if (FLAG_TEST_ALL (c->xfwm_flags,
XFWM_FLAG_HAS_RESIZE | XFWM_FLAG_IS_RESIZABLE))
{
clientResize (c, corner, ev);
}
else if (FLAG_TEST (c->xfwm_flags, XFWM_FLAG_HAS_MOVE))
{
clientMove (c, ev);
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));
handleMotionNotify (DisplayInfo *display_info, XMotionEvent * ev)
Olivier Fourdan
committed
{
TRACE ("entering handleMotionNotify");
Olivier Fourdan
committed
}
static int
getKeyPressed (ScreenInfo *screen_info, XKeyEvent * ev)
state = ev->state & MODIFIER_MASK;
for (key = 0; key < KEY_LAST; key++)
if ((screen_info->params->keys[key].keycode == ev->keycode)
&& (screen_info->params->keys[key].modifier == state))
{
break;
}
static void
handleKeyPress (DisplayInfo *display_info, XKeyEvent * ev)
{
int key;
TRACE ("entering handleKeyEvent");
c = clientGetFocus ();
key = getKeyPressed (screen_info, ev);
Olivier Fourdan
committed
switch (key)
{
case KEY_MOVE_UP:
case KEY_MOVE_DOWN:
case KEY_MOVE_LEFT:
case KEY_MOVE_RIGHT:
moveRequest (c, (XEvent *) ev);
break;
case KEY_RESIZE_UP:
case KEY_RESIZE_DOWN:
case KEY_RESIZE_LEFT:
case KEY_RESIZE_RIGHT:
Olivier Fourdan
committed
if (FLAG_TEST_ALL (c->xfwm_flags, XFWM_FLAG_HAS_RESIZE | XFWM_FLAG_IS_RESIZABLE))
{
clientResize (c, CORNER_BOTTOM_RIGHT, (XEvent *) ev);
}
break;
case KEY_CYCLE_WINDOWS:
clientCycle (c, (XEvent *) ev);
break;
case KEY_CLOSE_WINDOW:
clientClose (c);
break;
case KEY_HIDE_WINDOW:
{
clientHide (c, c->win_workspace, TRUE);
}
break;
case KEY_MAXIMIZE_WINDOW:
clientToggleMaximized (c, WIN_STATE_MAXIMIZED, TRUE);
break;
case KEY_MAXIMIZE_VERT:
clientToggleMaximized (c, WIN_STATE_MAXIMIZED_VERT, TRUE);
break;
case KEY_MAXIMIZE_HORIZ:
clientToggleMaximized (c, WIN_STATE_MAXIMIZED_HORIZ, TRUE);
break;
case KEY_SHADE_WINDOW:
clientToggleShaded (c);
break;
case KEY_STICK_WINDOW:
{
clientToggleSticky (c, TRUE);
Olivier Fourdan
committed
frameDraw (c, FALSE);
Olivier Fourdan
committed
}
Olivier Fourdan
committed
clientRaise (c, None);
Olivier Fourdan
committed
clientLower (c, None);
case KEY_TOGGLE_FULLSCREEN:
clientToggleFullscreen (c);
break;
case KEY_MOVE_NEXT_WORKSPACE:
Olivier Fourdan
committed
workspaceSwitch (screen_info, screen_info->current_ws + 1, c, TRUE);
break;
case KEY_MOVE_PREV_WORKSPACE:
Olivier Fourdan
committed
workspaceSwitch (screen_info, screen_info->current_ws - 1, c, TRUE);
Olivier Fourdan
committed
case KEY_MOVE_UP_WORKSPACE:
workspaceMove (screen_info, -1, 0, c);
break;
case KEY_MOVE_DOWN_WORKSPACE:
workspaceMove (screen_info, 1, 0, c);
break;
case KEY_MOVE_LEFT_WORKSPACE:
workspaceMove (screen_info, 0, -1, c);
break;
case KEY_MOVE_RIGHT_WORKSPACE:
workspaceMove (screen_info, 0, 1, c);
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:
Olivier Fourdan
committed
if (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);
Olivier Fourdan
committed
}
Olivier Fourdan
committed
case KEY_POPUP_MENU:
/*
We need to release the events here prior to grabbing
the keyboard in gtk menu otherwise we end with a dead lock...
*/
XAllowEvents (display_info->dpy, AsyncKeyboard, CurrentTime);
show_window_menu (c, frameX (c) + frameLeft (c),
frameY (c) + frameTop (c),
Button1, GDK_CURRENT_TIME);
/* 'nuff for now */
return;
Olivier Fourdan
committed
break;
default:
break;
}
Olivier Fourdan
committed
}
else
{
screen_info = myDisplayGetScreenFromRoot (display_info, ev->root);
if (!screen_info)
{
return;
}
key = getKeyPressed (screen_info, ev);
switch (key)
{
case KEY_CYCLE_WINDOWS:
clientCycle (screen_info->clients->prev, (XEvent *) ev);
Olivier Fourdan
committed
case KEY_CLOSE_WINDOW:
if (display_info->session)
{
logout_session (display_info->session);
}
break;
default:
break;
}
Olivier Fourdan
committed
}
/*
Here we know that "screen_info" is defined, otherwise, we would
Olivier Fourdan
committed
switch (key)
{
case KEY_NEXT_WORKSPACE:
Olivier Fourdan
committed
workspaceSwitch (screen_info, screen_info->current_ws + 1, NULL, TRUE);
break;
case KEY_PREV_WORKSPACE:
Olivier Fourdan
committed
workspaceSwitch (screen_info, screen_info->current_ws - 1, NULL, TRUE);
Olivier Fourdan
committed
case KEY_UP_WORKSPACE:
workspaceMove(screen_info, -1, 0, NULL);
break;
case KEY_DOWN_WORKSPACE:
workspaceMove(screen_info, 1, 0, NULL);
break;
case KEY_LEFT_WORKSPACE:
workspaceMove(screen_info, 0, -1, NULL);
break;
case KEY_RIGHT_WORKSPACE:
workspaceMove(screen_info, 0, 1, NULL);
break;
case KEY_ADD_WORKSPACE:
workspaceSetCount (screen_info, screen_info->workspace_count + 1);
break;
case KEY_DEL_WORKSPACE:
workspaceSetCount (screen_info, screen_info->workspace_count - 1);
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:
Olivier Fourdan
committed
if (key - KEY_WORKSPACE_1 < screen_info->workspace_count)
{
Olivier Fourdan
committed
workspaceSwitch (screen_info, key - KEY_WORKSPACE_1, NULL, TRUE);
Olivier Fourdan
committed
}
case KEY_SHOW_DESKTOP:
toggle_show_desktop (screen_info);
break;
default:
break;
Olivier Fourdan
committed
XAllowEvents (display_info->dpy, AsyncKeyboard, CurrentTime);
/* 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)
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)
{
moveRequest (c, (XEvent *) ev);
}
if (ev->button == Button1)
{
if (!(c->type & WINDOW_TYPE_DONT_FOCUS))
{
clientSetFocus (c->screen_info, c, ev->time, NO_FOCUS_FLAG);
}
Olivier Fourdan
committed
clientRaise (c, None);
}
if ((ev->button == Button1) || (ev->button == Button3))
{
resizeRequest (c, part, (XEvent *) ev);
}
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))
moveRequest (c, (XEvent *) ev);
else if (tclick == XFWM_BUTTON_DOUBLE_CLICK)
switch (screen_info->params->double_click_action)
{
case ACTION_MAXIMIZE:
clientToggleMaximized (c, WIN_STATE_MAXIMIZED, TRUE);
break;
case ACTION_SHADE:
clientToggleShaded (c);
break;
case ACTION_HIDE:
if (CLIENT_CAN_HIDE_WINDOW (c))
{
clientHide (c, c->win_workspace, TRUE);
}
titleButton (Client * c, int 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)
{
moveRequest (c, (XEvent *) ev);
}
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 Time lastscroll = (Time) 0;
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);
}
else if (ev->button == Button5)
{
Olivier Fourdan
committed
workspaceSwitch (screen_info, screen_info->current_ws + 1, NULL, TRUE);
}
}
handleButtonPress (DisplayInfo *display_info, XButtonEvent * ev)
TRACE ("entering handleButtonPress");
Olivier Fourdan
committed
#if CHECK_BUTTON_TIME
Olivier Fourdan
committed
/* Avoid treating the same event twice */
if (!check_button_time (ev))
{
TRACE ("ignoring ButtonPress event because it has been already handled");
return;
}
Olivier Fourdan
committed
#endif
c = myDisplayGetClientFromWindow (display_info, ev->window, ANY);
win = ev->subwindow;
Olivier Fourdan
committed
if ((ev->button == Button1) && (screen_info->params->easy_click) && (state == screen_info->params->easy_click))
{
button1Action (c, ev);
}
Olivier Fourdan
committed
else if ((ev->button == Button2) && (screen_info->params->easy_click) && (state == screen_info->params->easy_click))
Olivier Fourdan
committed
clientLower (c, None);
Olivier Fourdan
committed
else if ((ev->button == Button3) && (screen_info->params->easy_click) && (state == screen_info->params->easy_click))
Olivier Fourdan
committed
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);
if (x_distance < x_corner_pixels && y_distance < y_corner_pixels)
Olivier Fourdan
committed
/* 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
{
Olivier Fourdan
committed
/* 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;
Olivier Fourdan
committed
}
else
{
part = CORNER_COUNT + SIDE_RIGHT;
Olivier Fourdan
committed
}
}
else
{
/* Top or bottom side */
if (ev->y < c->height / 2)
{
part = CORNER_COUNT + SIDE_TOP;
Olivier Fourdan
committed
}
else
{
part = CORNER_COUNT + SIDE_BOTTOM;
Olivier Fourdan
committed
}
}
Olivier Fourdan
committed
edgeButton (c, part, ev);
}
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);
}
/* Clear timeout */
clear_timeout ();
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);
}
/* Clear timeout */
clear_timeout ();
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);
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
/* Let GTK handle this for us. */
}
}
}
else if ((win == MYWINDOW_XWINDOW (c->corners[CORNER_TOP_LEFT]))
&& (state == 0))
{
edgeButton (c, CORNER_TOP_LEFT, ev);
}
else if ((win == MYWINDOW_XWINDOW (c->corners[CORNER_TOP_RIGHT]))
&& (state == 0))
{
edgeButton (c, CORNER_TOP_RIGHT, ev);
}
else if ((win == MYWINDOW_XWINDOW (c->corners[CORNER_BOTTOM_LEFT]))
&& (state == 0))
{
edgeButton (c, CORNER_BOTTOM_LEFT, ev);
}
else if ((win == MYWINDOW_XWINDOW (c->corners[CORNER_BOTTOM_RIGHT]))
&& (state == 0))
{
edgeButton (c, CORNER_BOTTOM_RIGHT, ev);
}
else if ((win == MYWINDOW_XWINDOW (c->sides[SIDE_BOTTOM]))
&& (state == 0))
{
edgeButton (c, CORNER_COUNT + SIDE_BOTTOM, ev);
}
else if ((win == MYWINDOW_XWINDOW (c->sides[SIDE_LEFT]))
&& (state == 0))
{
edgeButton (c, CORNER_COUNT + SIDE_LEFT, ev);
}
else if ((win == MYWINDOW_XWINDOW (c->sides[SIDE_RIGHT]))
&& (state == 0))
{
edgeButton (c, CORNER_COUNT + SIDE_RIGHT, ev);