/*
** EPIwm
** Copyright (C) 1999 Julien Mulot, Thomas Poindessous, Stephane Rault
**
** 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 of the License, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
**
** mouse_events.c
**
** Made by (Poindessous Thomas)
** Login <poinde_t@epita.fr>
**
** Started on Wed Feb 24 15:19:04 1999 Poindessous Thomas
** Last update Wed Apr 5 02:28:13 2000 Mulot Julien
*/
#include "epiwm.h"
void handle_mouse()
{
Window child;
Window root;
int root_x;
int root_y;
int win_x;
int win_y;
unsigned int status;
t_menu_pos **p_menu;
if (gl_menu.menu_task == gl_event.xbutton.window)
menu_task_click(gl_event.xmotion.y);
else if (gl_menu.menu_prop == gl_event.xbutton.window)
menu_prop_click(gl_event.xmotion.y);
else if (gl_menu.workspace == gl_event.xbutton.window)
menu_workspace_click(gl_event.xmotion.y);
else
{
p_menu = &menu_pos;
while ((*p_menu) != NULL)
{
if (((*p_menu)->win) == gl_event.xbutton.window)
break;
p_menu = &((*p_menu)->next);
}
if ((*p_menu))
{
XQueryPointer(gl_dpy, gl_event.xbutton.window, &root, &child,
&root_x, &root_y, &win_x, &win_y, &status);
menu_click(*p_menu, win_y, status);
}
else
menu_display(gl_event.xbutton.window, gl_event.xbutton.x,
gl_event.xbutton.y, gl_event.xbutton.button);
}
}
void mouse_on_menu(t_menu_pos *menu)
{
int i;
int elt_pos;
int text_width;
t_menu_apps *p_menu_apps;
p_menu_apps = *(menu->pos);
elt_pos = gl_event.xmotion.y / gl_menu.height + 1;
for (i = 0; i < elt_pos; i++)
{
p_menu_apps = p_menu_apps->next_elt;
if (!p_menu_apps)
break;
}
if (p_menu_apps)
{
if (gl_menu.current_elt != &(p_menu_apps->elt))
{
menu_app_update(menu->pos, &menu);
text_width = XTextWidth(gl_menu.font, p_menu_apps->elt,
strlen(p_menu_apps->elt));
XDrawString(gl_dpy, menu->win, gl_menu.font_active,
(gl_menu.width - text_width) / 2,
elt_pos * gl_menu.height, p_menu_apps->elt,
strlen(p_menu_apps->elt));
if (p_menu_apps->menu)
draw_triangle(menu->win, gl_menu.width - 14,
elt_pos * gl_menu.height - 8, "active");
gl_menu.current_elt = &(p_menu_apps->elt);
}
}
}
void catch_win_mouse()
{
Window child;
Window root;
int root_x;
int root_y;
int win_x;
int win_y;
unsigned int status;
t_win *ewin;
XQueryPointer(gl_dpy, gl_scr_info.root_win, &root, &child,
&root_x, &root_y, &win_x, &win_y, &status);
ewin = search_elt(child);
if (ewin)
if (child == ewin->parent)
if ((gl_epiwin.focus_mode == FOCUS_SLOPPY)
|| (gl_epiwin.focus_mode == FOCUS_FOLLOW_MOUSE))
window_state(ewin, "active");
}
void mouse_enter_win()
{
t_win *ewin;
if (gl_event.xcrossing.window != gl_scr_info.root_win)
{
if (gl_event.xcrossing.window == gl_menu.menu_prop)
{
if (gl_epiwin.focus_mode == FOCUS_FOLLOW_MOUSE)
if (gl_menu.prop_type == FUNC_WIN)
gl_epiwin.current = gl_epiwin.left_win;
}
else
{
ewin = search_elt(gl_event.xcrossing.window);
if (ewin)
{
if (ewin->iconify_title_win == gl_event.xcrossing.window)
mouse_on_icon(gl_event.xcrossing.window);
else if (ewin->parent == gl_event.xcrossing.window)
{
if (gl_epiwin.prop & AUTO_RAISE)
XRaiseWindow(gl_dpy, ewin->parent);
if ((gl_epiwin.focus_mode == FOCUS_FOLLOW_MOUSE)
|| (gl_epiwin.focus_mode == FOCUS_SLOPPY))
window_state(ewin, "active");
}
}
}
}
}
void mouse_leave_win()
{
t_win *ewin;
t_menu_pos **menu;
if (gl_event.xcrossing.window != gl_scr_info.root_win)
{
if (gl_event.xcrossing.window == gl_menu.menu_task)
{
menu_task_update();
gl_menu.current_task = NULL;
}
else if (gl_event.xcrossing.window == gl_menu.menu_prop)
{
menu_prop_update();
gl_menu.current_prop = NULL;
}
else if (gl_event.xcrossing.window == gl_menu.workspace)
{
menu_workspace_update();
gl_menu.current_workspace = NULL;
}
else
{
ewin = search_elt(gl_event.xcrossing.window);
if (ewin)
{
if (ewin->iconify_title_win == gl_event.xcrossing.window)
mouse_out_icon(gl_event.xcrossing.window);
else if (ewin->parent == gl_event.xcrossing.window)
{
if (gl_epiwin.focus_mode == FOCUS_FOLLOW_MOUSE)
{
gl_epiwin.left_win = gl_epiwin.current;
window_state(ewin, "inactive");
gl_epiwin.current = NULL;
}
}
}
else
{
menu = &menu_pos;
while ((*menu) != NULL)
{
if ((*menu)->win == gl_event.xcrossing.window)
break;
menu = &((*menu)->next);
}
if (((*menu) != NULL) && ((*menu)->here))
{
gl_menu.current_elt = NULL;
if (!gl_menu.grad_type)
XClearArea(gl_dpy, (*menu)->win, gl_menu.width - 14, 0,
14, menu_set_height(*menu), False);
draw_menu((*menu)->pos, menu);
}
}
}
}
}
void mouse_press()
{
XWindowAttributes attrib;
XButtonEvent *button;
t_win *ewin;
int dummy_int;
Window dummy_win;
button = &gl_event.xbutton;
gl_win_move.bef = gl_win_move.win;
gl_win_move.win = button->window;
gl_win_move.mouse_x = button->x_root;
gl_win_move.mouse_y = button->y_root;
gl_win_move.win_x = button->x;
gl_win_move.win_y = button->y;
gl_win_move.time_press = button->time;
ewin = search_elt(button->window);
if (ewin)
{
/* if (gl_epiwin.focus_mode == FOCUS_CLICK)*/
window_state(ewin, "active");
XGetWindowAttributes(gl_dpy, ewin->border_frame , &attrib);
gl_win_move.width = attrib.width;
gl_win_move.height = attrib.height;
XRaiseWindow(gl_dpy, ewin->parent);
XGetWindowAttributes(gl_dpy, ewin->parent , &attrib);
gl_epiwin.opaque_x = attrib.x;
gl_epiwin.opaque_y = attrib.y;
gl_epiwin.opaque_width = attrib.width;
gl_epiwin.opaque_height = attrib.height;
gl_win_move.mouse_x = button->x_root - attrib.x;
gl_win_move.mouse_y = button->y_root - attrib.y;
gl_epiwin.prop |= IS_WIN_CHG;
XGetGeometry(gl_dpy, ewin->parent, &dummy_win, &dummy_int,
&dummy_int, &gl_epiwin.current_win_width,
&gl_epiwin.current_win_height,
&gl_epiwin.current_win_border_width, &dummy_int);
if (gl_menu.here_prop)
if (gl_menu.prop_type == FUNC_WIN)
menu_prop(0, 0, 0, 0);
}
if (gl_current_func)
{
if (ewin)
{
gl_menu.prop_type = FUNC_WIN;
gl_current_func();
win_func_terminate();
}
else if (button->window == gl_scr_info.root_win)
win_func_terminate();
}
else
handle_mouse();
}
void mouse_on_icon(icon)
Window icon;
{
char *name;
int font_direction;
int top_size;
int bottom_size;
XCharStruct dim;
#ifdef IMLIB
if (gl_icon.image_active)
draw_icon_image(icon, "active");
else
{
#endif
XSetWindowBackground(gl_dpy, icon, gl_icon.color_active.pixel);
XClearWindow(gl_dpy, icon);
#ifdef IMLIB
}
#endif
XGetIconName(gl_dpy, icon, &name);
XTextExtents(gl_icon.font, name, strlen(name), &font_direction,
&top_size, &bottom_size, &dim);
if ((dim.width + 6) > gl_icon.width)
{
XResizeWindow(gl_dpy, icon, dim.width + 6, gl_icon.height);
draw_icon(icon, dim.width + 6, "active");
}
else
{
XResizeWindow(gl_dpy, icon, gl_icon.width, gl_icon.height);
draw_icon(icon, gl_icon.width, "active");
}
free(name);
}
void mouse_out_icon(Window icon)
{
#ifdef IMLIB
if (gl_icon.image_active)
draw_icon_image(icon, "inactive");
else
{
#endif
XSetWindowBackground(gl_dpy, icon, gl_icon.color_inactive.pixel);
XClearWindow(gl_dpy, icon);
#ifdef IMLIB
}
#endif
XResizeWindow(gl_dpy, icon, gl_icon.width, gl_icon.height);
draw_icon(icon, gl_icon.width, "inactive");
}
void mouse_release()
{
t_mouse_move_win list;
if (gl_epiwin.opaque_mvt == 1)
{
gl_epiwin.opaque_mvt = 0;
XDrawRectangle(gl_dpy, gl_scr_info.root_win, gc_xor,
gl_epiwin.opaque_x, gl_epiwin.opaque_y,
gl_epiwin.opaque_width,
gl_epiwin.opaque_height);
XUngrabPointer(gl_dpy, CurrentTime);
XUngrabServer(gl_dpy);
XSync(gl_dpy, False);
}
list.button = &gl_event.xbutton;
gl_epiwin.prop &= ~IS_WIN_CHG;
if (!(Button1Mask == (list.button->state & Button1Mask)))
return ;
list.ewin = search_elt(list.button->window);
if (!list.ewin)
return ;
if (list.ewin->button_close == list.button->window)
win_close(list.ewin, 0, 0);
else if (list.ewin->button_destroy == list.button->window)
win_destroy(list.ewin, 0, 0);
else if (list.ewin->button_shade == list.button->window)
win_shade(list.ewin, 0, 0);
else if (list.ewin->button_max_height == list.button->window)
win_max_height(list.ewin);
else if (list.ewin->button_max_width == list.button->window)
win_max_width(list.ewin);
if (list.ewin->button_max == list.button->window)
mouse_resize_max(&list);
else if (list.ewin->button_iconify == list.button->window)
{
if ((list.button->x >= 0) && (list.button->y >= 0) &&
(list.button->x <= gl_epiwin.btn_width)
&& (list.button->y <= gl_epiwin.btn_height))
mouse_iconify(list.ewin);
}
else if (((list.ewin->iconify_title_win == list.button->window)
|| (list.ewin->iconify_win == list.button->window))
&& ((list.button->time - gl_win_move.time_press) < TIME_RELEASE))
mouse_uniconify(list.ewin);
else if (((list.button->time - gl_win_move.time_press) < TIME_RELEASE) &&
list.ewin->titlebar_win == list.button->window)
mouse_shade(&list);
else if (list.ewin->titlebar_win == list.button->window)
mouse_move_win(&list);
else if (list.ewin->win == list.button->window)
mouse_resize_l_r_d(&list);
gl_win_move.last = list.button->time;
}
void mouse_iconify(t_win *ewin)
{
char *name;
XGetIconName(gl_dpy, ewin->parent, &name);
ewin->iconify_title_win = add_iconify_win(ewin);
XSetIconName(gl_dpy, ewin->iconify_title_win, name);
free(name);
XUnmapWindow(gl_dpy, ewin->parent);
if (gl_icon.showed)
{
if (ewin->iconify_win)
{
XLowerWindow(gl_dpy, ewin->iconify_win);
XMapWindow(gl_dpy, ewin->iconify_win);
}
XLowerWindow(gl_dpy, ewin->iconify_title_win);
XMapWindow(gl_dpy, ewin->iconify_title_win);
#ifdef IMLIB
if (gl_icon.image_inactive)
draw_icon_image(ewin->iconify_title_win, "inactive");
#endif
draw_icon(ewin->iconify_title_win, gl_icon.width, "inactive");
}
clientSetState(ewin, IconicState);
}
void mouse_uniconify(t_win *ewin)
{
XDestroyWindow(gl_dpy, ewin->iconify_title_win);
if (ewin->iconify_win)
XUnmapWindow(gl_dpy, ewin->iconify_win);
iconify_rm_elt(ewin);
XMapWindow(gl_dpy, ewin->parent);
clientSetState(ewin, NormalState);
}
void mouse_move_win(t_mouse_move_win *list)
{
int x_root;
int y_root;
t_coord *coord;
if (gl_epiwin.prop & OPAQ_MOVE)
{
coord = window_on_border(list->ewin,
gl_epiwin.opaque_x, gl_epiwin.opaque_y);
XMoveWindow(gl_dpy, list->ewin->parent,
coord->x, coord->y);
if (coord->x == gl_epiwin.opaque_x)
gl_epiwin.cursor_position_x = -1;
if (coord->y == gl_epiwin.opaque_y)
gl_epiwin.cursor_position_y = -1;
free (coord);
}
else
{
x_root = gl_event.xmotion.x_root - gl_win_move.mouse_x;
y_root = gl_event.xmotion.y_root - gl_win_move.mouse_y;
coord = window_on_border(list->ewin, x_root, y_root);
XMoveWindow(gl_dpy, list->ewin->parent, coord->x, coord->y);
if (coord->x == x_root)
gl_epiwin.cursor_position_x = -1;
if (coord->y == y_root)
gl_epiwin.cursor_position_y = -1;
free (coord);
}
clientSetState(list->ewin, NormalState);
send_configure_notify(list->ewin);
}
void mouse_resize_l_r_d(t_mouse_move_win *list)
{
window_group_resize(list->ewin, gl_epiwin.opaque_x, gl_epiwin.opaque_y,
gl_epiwin.opaque_width, gl_epiwin.opaque_height);
send_configure_notify(list->ewin);
}
void mouse_on_border_notify()
{
if (gl_event.xmotion.x_root == gl_scr_info.dpy_width - 1)
wait_before_change_workspace('r');
else if (gl_event.xmotion.x_root == 0)
wait_before_change_workspace('l');
else
if ((gl_epiwin.current_cursor != gl_epiwin.normal_cursor)
&& (!gl_current_func))
XDefineCursor(gl_dpy, gl_scr_info.root_win, gl_epiwin.normal_cursor);
}
t_coord *window_on_border(t_win *ewin,
int x,
int y)
{
int rgt;
int dwn;
t_coord *coord;
t_bicoord *bicoord;
rgt = x + gl_epiwin.current_win_width +
2 * gl_epiwin.current_win_border_width + gl_epiwin.virtual_x;
dwn = y + gl_epiwin.current_win_height +
2 * gl_epiwin.current_win_border_width;
coord = (t_coord *) xmalloc(sizeof (t_coord));
coord->x = x;
coord->y = y;
if ((rgt >= (gl_epiwin.virtual_x + gl_scr_info.dpy_width)) &&
(rgt <= (gl_epiwin.virtual_x + gl_scr_info.dpy_width +
gl_workspace_time_change)))
{
bicoord = set_cursor_position();
if (((bicoord->x - gl_epiwin.cursor_position_x) <
gl_workspace_time_change) &&
(bicoord->x >= gl_epiwin.cursor_position_x) &&
(bicoord->win_x < x))
coord->x = gl_scr_info.dpy_width -
gl_epiwin.current_win_width -
2 * gl_epiwin.current_win_border_width;
free (bicoord);
}
else if (((x + gl_epiwin.virtual_x) <= gl_epiwin.virtual_x) &&
((x + gl_epiwin.virtual_x) >= (gl_epiwin.virtual_x -
gl_workspace_time_change)))
{
bicoord = set_cursor_position();
if (((gl_epiwin.cursor_position_x - bicoord->x) <
gl_workspace_time_change) &&
(bicoord->x <= gl_epiwin.cursor_position_x) &&
(bicoord->win_x > x))
coord->x = 0;
free (bicoord);
}
if ((dwn >= gl_scr_info.dpy_height) &&
(dwn <= gl_scr_info.dpy_height + gl_workspace_time_change))
{
bicoord = set_cursor_position();
if (((bicoord->y - gl_epiwin.cursor_position_y) <
gl_workspace_time_change) &&
(bicoord->y >= gl_epiwin.cursor_position_y) &&
(bicoord->win_y < y))
coord->y = gl_scr_info.dpy_height -
gl_epiwin.current_win_height -
2 * gl_epiwin.current_win_border_width;
free (bicoord);
}
else if ((y <= 0) &&
(y >= -gl_workspace_time_change))
{
bicoord = set_cursor_position();
if (((gl_epiwin.cursor_position_y - bicoord->y) <
gl_workspace_time_change) &&
(bicoord->y <= gl_epiwin.cursor_position_y) &&
(bicoord->win_y > y))
coord->y = 0;
free (bicoord);
}
return (coord);
}
t_bicoord *set_cursor_position()
{
Window dummy_win;
int dummy_int;
int cur_win_x;
int cur_win_y;
t_bicoord *bicoord;
bicoord = (t_bicoord *) xmalloc(sizeof (t_bicoord));
XQueryPointer(gl_dpy, gl_event.xbutton.window, &dummy_win, &dummy_win,
&(bicoord->x), &(bicoord->y), &cur_win_x, &cur_win_y,
&dummy_int);
bicoord->win_x = bicoord->x - cur_win_x;
bicoord->win_y = bicoord->y - cur_win_y;
if (gl_epiwin.cursor_position_x == -1)
gl_epiwin.cursor_position_x = bicoord->x;
if (gl_epiwin.cursor_position_y == -1)
gl_epiwin.cursor_position_y = bicoord->y;
return (bicoord);
}
syntax highlighted by Code2HTML, v. 0.9.1