This commit is contained in:
rhp 2001-06-20 04:29:28 +00:00
parent ca69bef032
commit 5fee634121
4 changed files with 361 additions and 57 deletions

View File

@ -75,3 +75,40 @@ meta_core_queue_frame_resize (Display *xdisplay,
meta_window_queue_move_resize (window); meta_window_queue_move_resize (window);
} }
void
meta_core_user_move (Display *xdisplay,
Window frame_xwindow,
int x,
int y)
{
MetaDisplay *display;
MetaWindow *window;
display = meta_display_for_x_display (xdisplay);
window = meta_display_lookup_x_window (display, frame_xwindow);
if (window == NULL || window->frame == NULL)
meta_bug ("No such frame window 0x%lx!\n", frame_xwindow);
window->user_has_moved = TRUE;
meta_window_move (window, x, y);
}
void
meta_core_get_position (Display *xdisplay,
Window frame_xwindow,
int *x,
int *y)
{
MetaDisplay *display;
MetaWindow *window;
display = meta_display_for_x_display (xdisplay);
window = meta_display_lookup_x_window (display, frame_xwindow);
if (window == NULL || window->frame == NULL)
meta_bug ("No such frame window 0x%lx!\n", frame_xwindow);
meta_window_get_position (window, x, y);
}

View File

@ -39,4 +39,18 @@ MetaFrameFlags meta_core_get_frame_flags (Display *xdisplay,
void meta_core_queue_frame_resize (Display *xdisplay, void meta_core_queue_frame_resize (Display *xdisplay,
Window frame_xwindow); Window frame_xwindow);
/* Move as a result of user operation */
void meta_core_user_move (Display *xdisplay,
Window frame_xwindow,
int x,
int y);
/* get position of client, same coord space expected by move */
void meta_core_get_position (Display *xdisplay,
Window frame_xwindow,
int *x,
int *y);
#endif #endif

View File

@ -89,6 +89,9 @@ struct _MetaFrameGeometry
int top_height; int top_height;
int bottom_height; int bottom_height;
int width;
int height;
GdkRectangle close_rect; GdkRectangle close_rect;
GdkRectangle max_rect; GdkRectangle max_rect;
GdkRectangle min_rect; GdkRectangle min_rect;
@ -97,53 +100,6 @@ struct _MetaFrameGeometry
GdkRectangle title_rect; GdkRectangle title_rect;
}; };
static GdkRectangle*
control_rect (MetaFrameControl control,
MetaFrameGeometry *fgeom)
{
GdkRectangle *rect;
rect = NULL;
switch (control)
{
case META_FRAME_CONTROL_TITLE:
rect = &fgeom->title_rect;
break;
case META_FRAME_CONTROL_DELETE:
rect = &fgeom->close_rect;
break;
case META_FRAME_CONTROL_MENU:
rect = &fgeom->menu_rect;
break;
case META_FRAME_CONTROL_MINIMIZE:
rect = &fgeom->min_rect;
break;
case META_FRAME_CONTROL_MAXIMIZE:
rect = &fgeom->max_rect;
break;
case META_FRAME_CONTROL_RESIZE_SE:
break;
case META_FRAME_CONTROL_RESIZE_S:
break;
case META_FRAME_CONTROL_RESIZE_SW:
break;
case META_FRAME_CONTROL_RESIZE_N:
break;
case META_FRAME_CONTROL_RESIZE_NE:
break;
case META_FRAME_CONTROL_RESIZE_NW:
break;
case META_FRAME_CONTROL_RESIZE_W:
break;
case META_FRAME_CONTROL_RESIZE_E:
break;
case META_FRAME_CONTROL_NONE:
break;
}
return rect;
}
static void meta_frames_class_init (MetaFramesClass *klass); static void meta_frames_class_init (MetaFramesClass *klass);
static void meta_frames_init (MetaFrames *frames); static void meta_frames_init (MetaFrames *frames);
static void meta_frames_destroy (GtkObject *object); static void meta_frames_destroy (GtkObject *object);
@ -194,6 +150,26 @@ static void meta_frames_calc_geometry (MetaFrames *frames,
static MetaUIFrame* meta_frames_lookup_window (MetaFrames *frames, static MetaUIFrame* meta_frames_lookup_window (MetaFrames *frames,
Window xwindow); Window xwindow);
static void meta_frames_begin_grab (MetaFrames *frames,
MetaUIFrame *frame,
MetaFrameStatus status,
int start_button,
int start_root_x,
int start_root_y,
int start_window_x,
int start_window_y,
guint32 timestamp);
static void meta_frames_end_grab (MetaFrames *frames,
guint32 timestamp);
static GdkRectangle* control_rect (MetaFrameControl control,
MetaFrameGeometry *fgeom);
static MetaFrameControl get_control (MetaFrames *frames,
MetaUIFrame *frame,
int x,
int y);
enum enum
{ {
LAST_SIGNAL LAST_SIGNAL
@ -264,6 +240,11 @@ meta_frames_class_init (MetaFramesClass *class)
widget_class->style_set = meta_frames_style_set; widget_class->style_set = meta_frames_style_set;
widget_class->expose_event = meta_frames_expose_event; widget_class->expose_event = meta_frames_expose_event;
widget_class->unmap_event = meta_frames_unmap_event;
widget_class->destroy_event = meta_frames_destroy_event;
widget_class->button_press_event = meta_frames_button_press_event;
widget_class->button_release_event = meta_frames_button_release_event;
widget_class->motion_notify_event = meta_frames_motion_notify_event;
INT_PROPERTY ("left_width", 6, _("Left edge"), _("Left window edge width")); INT_PROPERTY ("left_width", 6, _("Left edge"), _("Left window edge width"));
INT_PROPERTY ("right_width", 6, _("Right edge"), _("Right window edge width")); INT_PROPERTY ("right_width", 6, _("Right edge"), _("Right window edge width"));
@ -315,6 +296,8 @@ meta_frames_init (MetaFrames *frames)
frames->props = g_new0 (MetaFrameProperties, 1); frames->props = g_new0 (MetaFrameProperties, 1);
frames->frames = g_hash_table_new (unsigned_long_hash, unsigned_long_equal); frames->frames = g_hash_table_new (unsigned_long_hash, unsigned_long_equal);
frames->grab_status = META_FRAME_STATUS_NORMAL;
} }
static void static void
@ -508,8 +491,11 @@ meta_frames_calc_geometry (MetaFrames *frames,
meta_core_get_frame_size (gdk_display, frame->xwindow, meta_core_get_frame_size (gdk_display, frame->xwindow,
&width, &height); &width, &height);
flags = meta_core_get_frame_flags (gdk_display, frame->xwindow); flags = meta_core_get_frame_flags (gdk_display, frame->xwindow);
fgeom->width = width;
fgeom->height = height;
buttons_height = props.button_height + buttons_height = props.button_height +
props.button_border.top + props.button_border.bottom; props.button_border.top + props.button_border.bottom;
@ -693,7 +679,6 @@ meta_frames_manage_window (MetaFrames *frames,
GDK_BUTTON_PRESS_MASK | GDK_BUTTON_PRESS_MASK |
GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_RELEASE_MASK |
GDK_STRUCTURE_MASK); GDK_STRUCTURE_MASK);
#endif
/* This shouldn't be required if we don't select for button /* This shouldn't be required if we don't select for button
* press in frame.c? * press in frame.c?
@ -706,6 +691,7 @@ meta_frames_manage_window (MetaFrames *frames,
False, None); False, None);
XFlush (gdk_display); XFlush (gdk_display);
#endif
frame->xwindow = xwindow; frame->xwindow = xwindow;
frame->layout = NULL; frame->layout = NULL;
@ -723,6 +709,9 @@ meta_frames_unmanage_window (MetaFrames *frames,
if (frame) if (frame)
{ {
if (frames->grab_frame == frame)
meta_frames_end_grab (frames, GDK_CURRENT_TIME);
g_hash_table_remove (frames->frames, &frame->xwindow); g_hash_table_remove (frames->frames, &frame->xwindow);
g_object_unref (G_OBJECT (frame->window)); g_object_unref (G_OBJECT (frame->window));
@ -823,19 +812,131 @@ meta_frames_set_title (MetaFrames *frames,
gdk_window_invalidate_rect (frame->window, NULL, FALSE); gdk_window_invalidate_rect (frame->window, NULL, FALSE);
} }
static void
meta_frames_begin_grab (MetaFrames *frames,
MetaUIFrame *frame,
MetaFrameStatus status,
int start_button,
int start_root_x,
int start_root_y,
int start_window_x,
int start_window_y,
guint32 timestamp)
{
g_return_if_fail (frames->grab_frame == NULL);
/* This grab isn't needed I don't think */
if (gdk_pointer_grab (frame->window,
FALSE,
GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_PRESS_MASK |
GDK_POINTER_MOTION_HINT_MASK | GDK_POINTER_MOTION_MASK,
NULL,
NULL,
timestamp) == GDK_GRAB_SUCCESS)
{
frames->grab_frame = frame;
frames->grab_status = status;
frames->start_button = start_button;
frames->start_root_x = start_root_x;
frames->start_root_y = start_root_y;
frames->start_window_x = start_window_x;
frames->start_window_y = start_window_y;
}
}
static void
meta_frames_end_grab (MetaFrames *frames,
guint32 timestamp)
{
if (frames->grab_frame)
{
frames->grab_frame = NULL;
frames->grab_status = META_FRAME_STATUS_NORMAL;
gdk_pointer_ungrab (timestamp);
}
}
static void
frame_query_root_pointer (MetaUIFrame *frame,
int *x, int *y)
{
Window root_return, child_return;
int root_x_return, root_y_return;
int win_x_return, win_y_return;
unsigned int mask_return;
XQueryPointer (gdk_display,
frame->xwindow,
&root_return,
&child_return,
&root_x_return,
&root_y_return,
&win_x_return,
&win_y_return,
&mask_return);
if (x)
*x = root_x_return;
if (y)
*y = root_y_return;
}
static void
update_move (MetaFrames *frames,
MetaUIFrame *frame,
int x,
int y)
{
int dx, dy;
dx = x - frames->start_root_x;
dy = y - frames->start_root_y;
meta_core_user_move (gdk_display,
frame->xwindow,
frames->start_window_x + dx,
frames->start_window_y + dy);
}
gboolean gboolean
meta_frames_button_press_event (GtkWidget *widget, meta_frames_button_press_event (GtkWidget *widget,
GdkEventButton *event) GdkEventButton *event)
{ {
MetaUIFrame *frame; MetaUIFrame *frame;
MetaFrames *frames; MetaFrames *frames;
MetaFrameControl control;
frames = META_FRAMES (widget); frames = META_FRAMES (widget);
if (frames->grab_frame != NULL)
return FALSE; /* already up to something */
frame = meta_frames_lookup_window (frames, GDK_WINDOW_XID (event->window)); frame = meta_frames_lookup_window (frames, GDK_WINDOW_XID (event->window));
if (frame == NULL) if (frame == NULL)
return FALSE; return FALSE;
control = get_control (frames, frame, event->x, event->y);
if (((control == META_FRAME_CONTROL_TITLE ||
control == META_FRAME_CONTROL_NONE) &&
event->button == 1) ||
event->button == 2)
{
int x, y;
meta_core_get_position (gdk_display,
frame->xwindow,
&x, &y);
meta_frames_begin_grab (frames, frame,
META_FRAME_STATUS_MOVING,
event->button,
event->x_root,
event->y_root,
x, y,
event->time);
}
return TRUE; return TRUE;
} }
@ -847,11 +948,27 @@ meta_frames_button_release_event (GtkWidget *widget,
MetaFrames *frames; MetaFrames *frames;
frames = META_FRAMES (widget); frames = META_FRAMES (widget);
frame = meta_frames_lookup_window (frames, GDK_WINDOW_XID (event->window)); frame = meta_frames_lookup_window (frames, GDK_WINDOW_XID (event->window));
if (frame == NULL) if (frame == NULL)
return FALSE; return FALSE;
if (frames->grab_frame == frame &&
frames->start_button == event->button)
{
meta_frames_end_grab (frames, event->time);
switch (frames->grab_status)
{
case META_FRAME_STATUS_MOVING:
update_move (frames, frame, event->x_root, event->y_root);
break;
case META_FRAME_STATUS_NORMAL:
break;
}
}
return TRUE; return TRUE;
} }
@ -861,13 +978,20 @@ meta_frames_motion_notify_event (GtkWidget *widget,
{ {
MetaUIFrame *frame; MetaUIFrame *frame;
MetaFrames *frames; MetaFrames *frames;
frames = META_FRAMES (widget); frames = META_FRAMES (widget);
frame = meta_frames_lookup_window (frames, GDK_WINDOW_XID (event->window)); frame = meta_frames_lookup_window (frames, GDK_WINDOW_XID (event->window));
if (frame == NULL) if (frame == NULL)
return FALSE; return FALSE;
if (frames->grab_status == META_FRAME_STATUS_MOVING)
{
int x, y;
frame_query_root_pointer (frame, &x, &y);
update_move (frames, frame, x, y);
}
return TRUE; return TRUE;
} }
@ -884,6 +1008,9 @@ meta_frames_destroy_event (GtkWidget *widget,
if (frame == NULL) if (frame == NULL)
return FALSE; return FALSE;
if (frames->grab_frame == frame)
meta_frames_end_grab (frames, GDK_CURRENT_TIME);
return TRUE; return TRUE;
} }
@ -1048,6 +1175,7 @@ meta_frames_expose_event (GtkWidget *widget,
fgeom.close_rect.y + inner.top); fgeom.close_rect.y + inner.top);
} }
#define THICK_LINE_WIDTH 3
if (fgeom.max_rect.width > 0 && fgeom.max_rect.height > 0) if (fgeom.max_rect.width > 0 && fgeom.max_rect.height > 0)
{ {
gdk_draw_rectangle (frame->window, gdk_draw_rectangle (frame->window,
@ -1058,7 +1186,7 @@ meta_frames_expose_event (GtkWidget *widget,
fgeom.max_rect.width - inner.left - inner.right, fgeom.max_rect.width - inner.left - inner.right,
fgeom.max_rect.height - inner.top - inner.bottom); fgeom.max_rect.height - inner.top - inner.bottom);
vals.line_width = 3; vals.line_width = THICK_LINE_WIDTH;
gdk_gc_set_values (widget->style->fg_gc[GTK_STATE_NORMAL], gdk_gc_set_values (widget->style->fg_gc[GTK_STATE_NORMAL],
&vals, &vals,
GDK_GC_LINE_WIDTH); GDK_GC_LINE_WIDTH);
@ -1068,7 +1196,7 @@ meta_frames_expose_event (GtkWidget *widget,
fgeom.max_rect.x + inner.left, fgeom.max_rect.x + inner.left,
fgeom.max_rect.y + inner.top, fgeom.max_rect.y + inner.top,
fgeom.max_rect.x + fgeom.max_rect.width - inner.right, fgeom.max_rect.x + fgeom.max_rect.width - inner.right,
fgeom.max_rect.y + fgeom.max_rect.height - inner.bottom); fgeom.max_rect.y + inner.top);
vals.line_width = 0; vals.line_width = 0;
gdk_gc_set_values (widget->style->fg_gc[GTK_STATE_NORMAL], gdk_gc_set_values (widget->style->fg_gc[GTK_STATE_NORMAL],
@ -1079,7 +1207,7 @@ meta_frames_expose_event (GtkWidget *widget,
if (fgeom.min_rect.width > 0 && fgeom.min_rect.height > 0) if (fgeom.min_rect.width > 0 && fgeom.min_rect.height > 0)
{ {
vals.line_width = 3; vals.line_width = THICK_LINE_WIDTH;
gdk_gc_set_values (widget->style->fg_gc[GTK_STATE_NORMAL], gdk_gc_set_values (widget->style->fg_gc[GTK_STATE_NORMAL],
&vals, &vals,
GDK_GC_LINE_WIDTH); GDK_GC_LINE_WIDTH);
@ -1087,15 +1215,16 @@ meta_frames_expose_event (GtkWidget *widget,
gdk_draw_line (frame->window, gdk_draw_line (frame->window,
widget->style->fg_gc[GTK_STATE_NORMAL], widget->style->fg_gc[GTK_STATE_NORMAL],
fgeom.min_rect.x + inner.left, fgeom.min_rect.x + inner.left,
fgeom.min_rect.y + inner.top, fgeom.min_rect.y + fgeom.min_rect.height - inner.bottom - THICK_LINE_WIDTH,
fgeom.min_rect.x + fgeom.min_rect.width - inner.right, fgeom.min_rect.x + fgeom.min_rect.width - inner.right,
fgeom.min_rect.y + fgeom.min_rect.height - inner.bottom); fgeom.min_rect.y + fgeom.min_rect.height - inner.bottom - THICK_LINE_WIDTH);
vals.line_width = 0; vals.line_width = 0;
gdk_gc_set_values (widget->style->fg_gc[GTK_STATE_NORMAL], gdk_gc_set_values (widget->style->fg_gc[GTK_STATE_NORMAL],
&vals, &vals,
GDK_GC_LINE_WIDTH); GDK_GC_LINE_WIDTH);
} }
#undef THICK_LINE_WIDTH
if (fgeom.spacer_rect.width > 0 && fgeom.spacer_rect.height > 0) if (fgeom.spacer_rect.width > 0 && fgeom.spacer_rect.height > 0)
{ {
@ -1274,6 +1403,9 @@ meta_frames_unmap_event (GtkWidget *widget,
if (frame == NULL) if (frame == NULL)
return FALSE; return FALSE;
if (frames->grab_frame == frame)
meta_frames_end_grab (frames, GDK_CURRENT_TIME);
return TRUE; return TRUE;
} }
@ -1326,6 +1458,110 @@ meta_frames_window_state_event (GtkWidget *widget,
} }
static GdkRectangle*
control_rect (MetaFrameControl control,
MetaFrameGeometry *fgeom)
{
GdkRectangle *rect;
rect = NULL;
switch (control)
{
case META_FRAME_CONTROL_TITLE:
rect = &fgeom->title_rect;
break;
case META_FRAME_CONTROL_DELETE:
rect = &fgeom->close_rect;
break;
case META_FRAME_CONTROL_MENU:
rect = &fgeom->menu_rect;
break;
case META_FRAME_CONTROL_MINIMIZE:
rect = &fgeom->min_rect;
break;
case META_FRAME_CONTROL_MAXIMIZE:
rect = &fgeom->max_rect;
break;
case META_FRAME_CONTROL_RESIZE_SE:
break;
case META_FRAME_CONTROL_RESIZE_S:
break;
case META_FRAME_CONTROL_RESIZE_SW:
break;
case META_FRAME_CONTROL_RESIZE_N:
break;
case META_FRAME_CONTROL_RESIZE_NE:
break;
case META_FRAME_CONTROL_RESIZE_NW:
break;
case META_FRAME_CONTROL_RESIZE_W:
break;
case META_FRAME_CONTROL_RESIZE_E:
break;
case META_FRAME_CONTROL_NONE:
break;
}
return rect;
}
#define POINT_IN_RECT(xcoord, ycoord, rect) \
((xcoord) >= (rect).x && \
(xcoord) < ((rect).x + (rect).width) && \
(ycoord) >= (rect).y && \
(ycoord) < ((rect).y + (rect).height))
#define RESIZE_EXTENDS 10
static MetaFrameControl
get_control (MetaFrames *frames,
MetaUIFrame *frame,
int x, int y)
{
MetaFrameGeometry fgeom;
meta_frames_calc_geometry (frames, frame, &fgeom);
if (POINT_IN_RECT (x, y, fgeom.close_rect))
return META_FRAME_CONTROL_DELETE;
if (POINT_IN_RECT (x, y, fgeom.min_rect))
return META_FRAME_CONTROL_MINIMIZE;
if (POINT_IN_RECT (x, y, fgeom.max_rect))
return META_FRAME_CONTROL_MAXIMIZE;
if (POINT_IN_RECT (x, y, fgeom.menu_rect))
return META_FRAME_CONTROL_MENU;
if (POINT_IN_RECT (x, y, fgeom.title_rect))
return META_FRAME_CONTROL_TITLE;
if (y > (fgeom.height - fgeom.bottom_height - RESIZE_EXTENDS) &&
x > (fgeom.width - fgeom.right_width - RESIZE_EXTENDS))
return META_FRAME_CONTROL_RESIZE_SE;
return META_FRAME_CONTROL_NONE;
}
#if 0 #if 0
static void static void

View File

@ -44,6 +44,13 @@ typedef enum
META_FRAME_CONTROL_RESIZE_E META_FRAME_CONTROL_RESIZE_E
} MetaFrameControl; } MetaFrameControl;
typedef enum
{
META_FRAME_STATUS_NORMAL,
META_FRAME_STATUS_MOVING
} MetaFrameStatus;
/* This is one widget that manages all the window frames /* This is one widget that manages all the window frames
* as subwindows. * as subwindows.
*/ */
@ -71,6 +78,16 @@ struct _MetaFrames
int text_height; int text_height;
GHashTable *frames; GHashTable *frames;
/* The below is all for grabs */
MetaFrameStatus grab_status;
MetaUIFrame *grab_frame;
/* initial mouse position for drags */
int start_root_x, start_root_y;
/* initial window size or initial window position for drags */
int start_window_x, start_window_y;
/* button doing the dragging */
int start_button;
}; };
struct _MetaFramesClass struct _MetaFramesClass