This commit is contained in:
rhp 2001-07-26 03:14:45 +00:00
parent 46edcc4832
commit b6e4c8bc41
15 changed files with 646 additions and 615 deletions

51
README
View File

@ -31,8 +31,10 @@ METACITY FEATURES
letter in the menu item works. letter in the menu item works.
Choose Move from menu, and arrow keys to move the window. Choose Move from menu, and arrow keys to move the window.
While moving, hold down Control to move slower, and While moving, hold down Control to move slower, and
Shift to snap to edges. Shift to snap to edges.
Choose Resize from menu, and nothing happens yet, but Choose Resize from menu, and nothing happens yet, but
eventually I might implement something. eventually I might implement something.
@ -85,11 +87,17 @@ METACITY FEATURES
look in frames.c:meta_frames_class_init() for all the style look in frames.c:meta_frames_class_init() for all the style
properties that you can configure. properties that you can configure.
Metacity-specific styles can also be included in any GTK+
theme.
- Metacity implements much of the new window manager spec from - Metacity implements much of the new window manager spec from
freedesktop.org, and much of the ICCCM. But then there are freedesktop.org, and much of the ICCCM. But then there are
parts of each that it doesn't implement, just because I haven't parts of each that it doesn't implement, just because I haven't
yet. yet.
- Uses Pango to render text, so has cool i18n capabilities.
Supports UTF-8 window titles and such.
METACITY BUGS, NON-FEATURES, AND CAVEATS METACITY BUGS, NON-FEATURES, AND CAVEATS
=== ===
@ -154,6 +162,17 @@ METACITY BUGS, NON-FEATURES, AND CAVEATS
Metacity needs to keep this area up-to-date using the hints the Metacity needs to keep this area up-to-date using the hints the
panel sets. panel sets.
- Should really support click-to-focus as an option.
- Windows has a neat way of implementing Alt-Tab for
window cycling that I would like to copy. (The little
popup window thing.)
- Should Metacity support flipping in right-to-left locales?
I don't know what window managers look like in a right-to-left
locale. I assume the window titles should be right-justified;
should the window controls also be flipped?
COMPILING METACITY COMPILING METACITY
=== ===
@ -161,22 +180,32 @@ You need GTK+ 1.3.x (to become 2.0). See configure.in for the exact
version you need. Metacity is a fairly trivial 6000-line C program, so version you need. Metacity is a fairly trivial 6000-line C program, so
once you get GTK+ built it should be no problem to build Metacity. once you get GTK+ built it should be no problem to build Metacity.
REPORTING BUGS REPORTING BUGS AND SUBMITTING PATCHES
=== ===
Report new bugs to hp@redhat.com for now. Will switch to Bugzilla Report new bugs to hp@redhat.com for now. Will switch to Bugzilla
sometime probably. sometime probably.
Feel free to send patches too; Metacity is really small and simple, so
if you find a bug or want to add a feature it should be pretty easy.
FAQ FAQ
=== ===
Q: Will you add my feature? Q: Will you add my feature?
A: Probably not, unless it makes sense to turn on by unconditionally, A: If it makes sense to turn on unconditionally,
or is genuinely a harmless preference that I would not or is genuinely a harmless preference that I would not
be embarrassed to put in a user-friendly configuration dialog. be embarrassed to put in a simple, uncluttered, user-friendly
configuration dialog.
Metacity has a "no crackrock" policy, with some exceptions If the only rationale for your feature is that other window
managers have it, or that you are personally used to it, or something
like that, then I will not be impressed. Metacity is firmly in the
"choose good defaults" camp rather than the "offer 6 equally broken
ways to do it, and let the user pick one" camp.
This is part of a "no crackrock" policy, despite some exceptions
I'm mildly embarrassed about. For example, multiple workspaces I'm mildly embarrassed about. For example, multiple workspaces
probably constitute crackrock, they confuse most users probably constitute crackrock, they confuse most users
and really are not that useful if you have a decent tasklist and and really are not that useful if you have a decent tasklist and
@ -187,6 +216,10 @@ A: Probably not, unless it makes sense to turn on by unconditionally,
But don't think unlimited crack is OK just because I slipped up a But don't think unlimited crack is OK just because I slipped up a
little. No slippery slope here. little. No slippery slope here.
Don't let this discourage patches and fixes - I love those. ;-)
Just be prepared to hear the above objections if your patch
adds some crack-ridden configuration option.
Q: How do I add a configuration option? Q: How do I add a configuration option?
A: You don't, until GConf 2 is relatively easy to compile and I feel A: You don't, until GConf 2 is relatively easy to compile and I feel
@ -196,10 +229,12 @@ Q: Will Metacity be part of GNOME?
A: If Metacity is ever better than the other options, and the GNOME A: If Metacity is ever better than the other options, and the GNOME
Project so chooses. But Metacity may continue to suck forever Project so chooses. But Metacity may continue to suck forever
because I might get tired of it; or Metacity's conservative because I might get tired of working on it; or Metacity's feature
nature might not make sense for the snazzy world of set might not make sense for GNOME. Who knows. I'm not worrying
GNOME. Who knows. I'm not worrying about this, and you shouldn't about this, and you shouldn't either.
either.
For now Metacity is my toy hobby project that I work on when I feel
like it.
Q: Why can't I move XMMS? Q: Why can't I move XMMS?

View File

@ -70,6 +70,7 @@ typedef void (* MetaWindowMenuFunc) (MetaWindowMenu *menu,
typedef enum typedef enum
{ {
META_GRAB_OP_NONE, META_GRAB_OP_NONE,
/* Mouse ops */
META_GRAB_OP_MOVING, META_GRAB_OP_MOVING,
META_GRAB_OP_RESIZING_SE, META_GRAB_OP_RESIZING_SE,
META_GRAB_OP_RESIZING_S, META_GRAB_OP_RESIZING_S,
@ -79,14 +80,35 @@ typedef enum
META_GRAB_OP_RESIZING_NW, META_GRAB_OP_RESIZING_NW,
META_GRAB_OP_RESIZING_W, META_GRAB_OP_RESIZING_W,
META_GRAB_OP_RESIZING_E, META_GRAB_OP_RESIZING_E,
/* Keyboard ops */
META_GRAB_OP_KEYBOARD_MOVING, META_GRAB_OP_KEYBOARD_MOVING,
META_GRAB_OP_KEYBOARD_RESIZING_UNKNOWN, META_GRAB_OP_KEYBOARD_RESIZING_UNKNOWN,
META_GRAB_OP_KEYBOARD_RESIZING_S, META_GRAB_OP_KEYBOARD_RESIZING_S,
META_GRAB_OP_KEYBOARD_RESIZING_N, META_GRAB_OP_KEYBOARD_RESIZING_N,
META_GRAB_OP_KEYBOARD_RESIZING_W, META_GRAB_OP_KEYBOARD_RESIZING_W,
META_GRAB_OP_KEYBOARD_RESIZING_E META_GRAB_OP_KEYBOARD_RESIZING_E,
/* Frame button ops */
META_GRAB_OP_CLICKING_MINIMIZE,
META_GRAB_OP_CLICKING_MAXIMIZE,
META_GRAB_OP_CLICKING_DELETE,
META_GRAB_OP_CLICKING_MENU
} MetaGrabOp; } MetaGrabOp;
typedef enum
{
META_CURSOR_DEFAULT,
META_CURSOR_NORTH_RESIZE,
META_CURSOR_SOUTH_RESIZE,
META_CURSOR_WEST_RESIZE,
META_CURSOR_EAST_RESIZE,
META_CURSOR_SE_RESIZE,
META_CURSOR_SW_RESIZE,
META_CURSOR_NE_RESIZE,
META_CURSOR_NW_RESIZE
} MetaCursor;
#endif #endif

View File

@ -393,3 +393,104 @@ meta_core_show_window_menu (Display *xdisplay,
meta_window_show_menu (window, root_x, root_y, button, timestamp); meta_window_show_menu (window, root_x, root_y, button, timestamp);
} }
gboolean
meta_core_begin_grab_op (Display *xdisplay,
Window frame_xwindow,
MetaGrabOp op,
gboolean pointer_already_grabbed,
int button,
gulong modmask,
Time timestamp,
int root_x,
int root_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);
return meta_display_begin_grab_op (display, window,
op, pointer_already_grabbed,
button, modmask,
timestamp, root_x, root_y);
}
void
meta_core_end_grab_op (Display *xdisplay,
Time timestamp)
{
MetaDisplay *display;
display = meta_display_for_x_display (xdisplay);
meta_display_end_grab_op (display, timestamp);
}
MetaGrabOp
meta_core_get_grab_op (Display *xdisplay)
{
MetaDisplay *display;
display = meta_display_for_x_display (xdisplay);
return display->grab_op;
}
Window
meta_core_get_grab_frame (Display *xdisplay)
{
MetaDisplay *display;
display = meta_display_for_x_display (xdisplay);
if (display->grab_op != META_GRAB_OP_NONE &&
display->grab_window->frame)
return display->grab_window->frame->xwindow;
else
return None;
}
int
meta_core_get_grab_button (Display *xdisplay)
{
MetaDisplay *display;
display = meta_display_for_x_display (xdisplay);
if (display->grab_op == META_GRAB_OP_NONE)
return -1;
return display->grab_button;
}
void
meta_core_grab_buttons (Display *xdisplay,
Window frame_xwindow)
{
MetaDisplay *display;
display = meta_display_for_x_display (xdisplay);
meta_display_grab_window_buttons (display, frame_xwindow);
}
void
meta_core_set_screen_cursor (Display *xdisplay,
Window frame_on_screen,
MetaCursor cursor)
{
MetaDisplay *display;
MetaWindow *window;
display = meta_display_for_x_display (xdisplay);
window = meta_display_lookup_x_window (display, frame_on_screen);
if (window == NULL || window->frame == NULL)
meta_bug ("No such frame window 0x%lx!\n", frame_on_screen);
meta_screen_set_cursor (window->screen, cursor);
}

View File

@ -94,7 +94,6 @@ int meta_core_get_active_workspace (Screen *xscreen);
int meta_core_get_frame_workspace (Display *xdisplay, int meta_core_get_frame_workspace (Display *xdisplay,
Window frame_xwindow); Window frame_xwindow);
void meta_core_show_window_menu (Display *xdisplay, void meta_core_show_window_menu (Display *xdisplay,
Window frame_xwindow, Window frame_xwindow,
int root_x, int root_x,
@ -102,6 +101,31 @@ void meta_core_show_window_menu (Display *xdisplay,
int button, int button,
Time timestamp); Time timestamp);
gboolean meta_core_begin_grab_op (Display *xdisplay,
Window frame_xwindow,
MetaGrabOp op,
gboolean pointer_already_grabbed,
int button,
gulong modmask,
Time timestamp,
int root_x,
int root_y);
void meta_core_end_grab_op (Display *xdisplay,
Time timestamp);
MetaGrabOp meta_core_get_grab_op (Display *xdisplay);
Window meta_core_get_grab_frame (Display *xdisplay);
int meta_core_get_grab_button (Display *xdisplay);
void meta_core_grab_buttons (Display *xdisplay,
Window frame_xwindow);
void meta_core_set_screen_cursor (Display *xdisplay,
Window frame_on_screen,
MetaCursor cursor);
#endif #endif

View File

@ -29,6 +29,7 @@
#include "keybindings.h" #include "keybindings.h"
#include "workspace.h" #include "workspace.h"
#include <X11/Xatom.h> #include <X11/Xatom.h>
#include <X11/cursorfont.h>
#include <string.h> #include <string.h>
#define USE_GDK_DISPLAY #define USE_GDK_DISPLAY
@ -554,6 +555,47 @@ event_queue_callback (XEvent *event,
event_callback (event, data); event_callback (event, data);
} }
static gboolean
grab_op_is_mouse (MetaGrabOp op)
{
switch (op)
{
case META_GRAB_OP_MOVING:
case META_GRAB_OP_RESIZING_SE:
case META_GRAB_OP_RESIZING_S:
case META_GRAB_OP_RESIZING_SW:
case META_GRAB_OP_RESIZING_N:
case META_GRAB_OP_RESIZING_NE:
case META_GRAB_OP_RESIZING_NW:
case META_GRAB_OP_RESIZING_W:
case META_GRAB_OP_RESIZING_E:
return TRUE;
break;
default:
return FALSE;
}
}
static gboolean
grab_op_is_keyboard (MetaGrabOp op)
{
switch (op)
{
case META_GRAB_OP_KEYBOARD_MOVING:
case META_GRAB_OP_KEYBOARD_RESIZING_UNKNOWN:
case META_GRAB_OP_KEYBOARD_RESIZING_S:
case META_GRAB_OP_KEYBOARD_RESIZING_N:
case META_GRAB_OP_KEYBOARD_RESIZING_W:
case META_GRAB_OP_KEYBOARD_RESIZING_E:
return TRUE;
break;
default:
return FALSE;
}
}
static gboolean static gboolean
event_callback (XEvent *event, event_callback (XEvent *event,
gpointer data) gpointer data)
@ -609,7 +651,10 @@ event_callback (XEvent *event,
meta_display_process_key_event (display, window, event); meta_display_process_key_event (display, window, event);
break; break;
case ButtonPress: case ButtonPress:
if (display->grab_op != META_GRAB_OP_NONE) if ((grab_op_is_mouse (display->grab_op) &&
display->grab_button != event->xbutton.button &&
display->grab_window == window) ||
grab_op_is_keyboard (display->grab_op))
{ {
meta_verbose ("Ending grab op %d on window %s due to button press\n", meta_verbose ("Ending grab op %d on window %s due to button press\n",
display->grab_op, display->grab_op,
@ -617,10 +662,37 @@ event_callback (XEvent *event,
meta_display_end_grab_op (display, meta_display_end_grab_op (display,
event->xbutton.time); event->xbutton.time);
} }
else if (window)
{
if (event->xbutton.button == 1)
{
meta_window_raise (window);
meta_window_focus (window, event->xbutton.time);
}
else if (event->xbutton.button == 2)
{
/* FIXME begin move */
}
else if (event->xbutton.button == 3)
{
meta_window_show_menu (window,
event->xbutton.x_root,
event->xbutton.y_root,
event->xbutton.button,
event->xbutton.time);
}
}
break; break;
case ButtonRelease: case ButtonRelease:
if (grab_op_is_mouse (display->grab_op) &&
display->grab_window == window)
meta_window_handle_mouse_grab_op_event (window, event);
break; break;
case MotionNotify: case MotionNotify:
if (grab_op_is_mouse (display->grab_op) &&
display->grab_window == window)
meta_window_handle_mouse_grab_op_event (window, event);
break; break;
case EnterNotify: case EnterNotify:
/* do this even if window->has_focus to avoid races */ /* do this even if window->has_focus to avoid races */
@ -649,6 +721,10 @@ event_callback (XEvent *event,
case DestroyNotify: case DestroyNotify:
if (window) if (window)
{ {
if (display->grab_op != META_GRAB_OP_NONE &&
display->grab_window == window)
meta_display_end_grab_op (display, CurrentTime);
if (frame_was_receiver) if (frame_was_receiver)
{ {
meta_warning ("Unexpected destruction of frame 0x%lx, not sure if this should silently fail or be considered a bug\n", meta_warning ("Unexpected destruction of frame 0x%lx, not sure if this should silently fail or be considered a bug\n",
@ -664,6 +740,14 @@ event_callback (XEvent *event,
} }
break; break;
case UnmapNotify: case UnmapNotify:
if (display->grab_op != META_GRAB_OP_NONE &&
display->grab_window == window)
meta_display_end_grab_op (display, CurrentTime);
/* Unfocus on UnmapNotify */
if (window)
meta_window_notify_focus (window, event);
if (!frame_was_receiver && window) if (!frame_was_receiver && window)
{ {
if (window->unmaps_pending == 0) if (window->unmaps_pending == 0)
@ -932,7 +1016,6 @@ static void
meta_spew_event (MetaDisplay *display, meta_spew_event (MetaDisplay *display,
XEvent *event) XEvent *event)
{ {
const char *name = NULL; const char *name = NULL;
char *extra = NULL; char *extra = NULL;
char *winname; char *winname;
@ -1208,6 +1291,94 @@ meta_display_get_workspace_by_screen_index (MetaDisplay *display,
return NULL; return NULL;
} }
Cursor
meta_display_create_x_cursor (MetaDisplay *display,
MetaCursor cursor)
{
Cursor xcursor;
guint glyph;
switch (cursor)
{
case META_CURSOR_DEFAULT:
glyph = XC_left_ptr;
break;
case META_CURSOR_NORTH_RESIZE:
glyph = XC_top_side;
break;
case META_CURSOR_SOUTH_RESIZE:
glyph = XC_bottom_side;
break;
case META_CURSOR_WEST_RESIZE:
glyph = XC_left_side;
break;
case META_CURSOR_EAST_RESIZE:
glyph = XC_right_side;
break;
case META_CURSOR_SE_RESIZE:
glyph = XC_bottom_right_corner;
break;
case META_CURSOR_SW_RESIZE:
glyph = XC_bottom_left_corner;
break;
case META_CURSOR_NE_RESIZE:
glyph = XC_top_left_corner;
break;
case META_CURSOR_NW_RESIZE:
glyph = XC_top_right_corner;
break;
default:
g_assert_not_reached ();
glyph = 0; /* silence compiler */
break;
}
xcursor = XCreateFontCursor (display->xdisplay, glyph);
return xcursor;
}
static Cursor
xcursor_for_op (MetaDisplay *display,
MetaGrabOp op)
{
MetaCursor cursor = META_CURSOR_DEFAULT;
switch (display->grab_op)
{
case META_GRAB_OP_RESIZING_SE:
cursor = META_CURSOR_SE_RESIZE;
break;
case META_GRAB_OP_RESIZING_S:
cursor = META_CURSOR_SOUTH_RESIZE;
break;
case META_GRAB_OP_RESIZING_SW:
cursor = META_CURSOR_SW_RESIZE;
break;
case META_GRAB_OP_RESIZING_N:
cursor = META_CURSOR_NORTH_RESIZE;
break;
case META_GRAB_OP_RESIZING_NE:
cursor = META_CURSOR_NE_RESIZE;
break;
case META_GRAB_OP_RESIZING_NW:
cursor = META_CURSOR_NW_RESIZE;
break;
case META_GRAB_OP_RESIZING_W:
cursor = META_CURSOR_WEST_RESIZE;
break;
case META_GRAB_OP_RESIZING_E:
cursor = META_CURSOR_EAST_RESIZE;
break;
default:
break;
}
return meta_display_create_x_cursor (display, cursor);
}
gboolean gboolean
meta_display_begin_grab_op (MetaDisplay *display, meta_display_begin_grab_op (MetaDisplay *display,
MetaWindow *window, MetaWindow *window,
@ -1215,12 +1386,12 @@ meta_display_begin_grab_op (MetaDisplay *display,
gboolean pointer_already_grabbed, gboolean pointer_already_grabbed,
int button, int button,
gulong modmask, gulong modmask,
Cursor cursor,
Time timestamp, Time timestamp,
int root_x, int root_x,
int root_y) int root_y)
{ {
Window grabwindow; Window grabwindow;
Cursor cursor;
meta_verbose ("Doing grab op %d on window %s button %d pointer already grabbed: %d\n", meta_verbose ("Doing grab op %d on window %s button %d pointer already grabbed: %d\n",
op, window->desc, button, pointer_already_grabbed); op, window->desc, button, pointer_already_grabbed);
@ -1235,11 +1406,14 @@ meta_display_begin_grab_op (MetaDisplay *display,
} }
if (pointer_already_grabbed) if (pointer_already_grabbed)
{
display->grab_have_pointer = TRUE; display->grab_have_pointer = TRUE;
}
else /* We XGrabPointer even if we already have an autograb,
{ * just to set the cursor and event mask
*/
cursor = xcursor_for_op (display, op);
meta_error_trap_push (display); meta_error_trap_push (display);
if (XGrabPointer (display->xdisplay, if (XGrabPointer (display->xdisplay,
grabwindow, grabwindow,
@ -1253,7 +1427,8 @@ meta_display_begin_grab_op (MetaDisplay *display,
timestamp) == GrabSuccess) timestamp) == GrabSuccess)
display->grab_have_pointer = TRUE; display->grab_have_pointer = TRUE;
meta_error_trap_pop (display); meta_error_trap_pop (display);
}
XFreeCursor (display->xdisplay, cursor);
if (!display->grab_have_pointer) if (!display->grab_have_pointer)
{ {
@ -1284,7 +1459,6 @@ meta_display_begin_grab_op (MetaDisplay *display,
break; break;
} }
display->grab_op = op; display->grab_op = op;
display->grab_window = window; display->grab_window = window;
display->grab_button = button; display->grab_button = button;
@ -1320,3 +1494,63 @@ meta_display_end_grab_op (MetaDisplay *display,
display->grab_window = NULL; display->grab_window = NULL;
display->grab_op = META_GRAB_OP_NONE; display->grab_op = META_GRAB_OP_NONE;
} }
void
meta_display_grab_window_buttons (MetaDisplay *display,
Window xwindow)
{
/* Grab Alt + button1 and Alt + button2 for moving window,
* and Alt + button3 for popping up window menu.
*/
{
int i = 1;
while (i < 4)
{
int result;
meta_error_trap_push (display);
XGrabButton (display->xdisplay, i, Mod1Mask,
xwindow, False,
ButtonPressMask | ButtonReleaseMask |
PointerMotionMask | PointerMotionHintMask,
GrabModeAsync, GrabModeAsync,
False, None);
XSync (display->xdisplay, False);
result = meta_error_trap_pop (display);
if (result != Success)
meta_warning ("Failed to grab button %d with Mod1Mask for frame 0x%lx error code %d\n",
i, xwindow, result);
#if 1
/* This is just for debugging, since I end up moving
* the Xnest otherwise ;-)
*/
meta_error_trap_push (display);
result = XGrabButton (display->xdisplay, i, ControlMask,
xwindow, False,
ButtonPressMask | ButtonReleaseMask |
PointerMotionMask | PointerMotionHintMask,
GrabModeAsync, GrabModeAsync,
False, None);
XSync (display->xdisplay, False);
result = meta_error_trap_pop (display);
if (result != Success)
meta_warning ("Failed to grab button %d with ControlMask for frame 0x%lx error code %d\n",
i, xwindow, result);
#endif
++i;
}
}
}
void
meta_display_ungrab_window_buttons (MetaDisplay *display,
Window xwindow)
{
}

View File

@ -163,19 +163,26 @@ MetaWorkspace* meta_display_get_workspace_by_index (MetaDisplay *displa
MetaWorkspace* meta_display_get_workspace_by_screen_index (MetaDisplay *display, MetaWorkspace* meta_display_get_workspace_by_screen_index (MetaDisplay *display,
MetaScreen *screen, MetaScreen *screen,
int index); int index);
Cursor meta_display_create_x_cursor (MetaDisplay *display,
MetaCursor cursor);
gboolean meta_display_begin_grab_op (MetaDisplay *display, gboolean meta_display_begin_grab_op (MetaDisplay *display,
MetaWindow *window, MetaWindow *window,
MetaGrabOp op, MetaGrabOp op,
gboolean pointer_already_grabbed, gboolean pointer_already_grabbed,
int button, int button,
gulong modmask, gulong modmask,
Cursor cursor,
Time timestamp, Time timestamp,
int root_x, int root_x,
int root_y); int root_y);
void meta_display_end_grab_op (MetaDisplay *display, void meta_display_end_grab_op (MetaDisplay *display,
Time timestamp); Time timestamp);
void meta_display_grab_window_buttons (MetaDisplay *display,
Window xwindow);
void meta_display_ungrab_window_buttons (MetaDisplay *display,
Window xwindow);
#endif #endif

View File

@ -137,20 +137,6 @@ 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,
int start_window_w,
int start_window_h,
guint32 timestamp);
static void meta_frames_end_grab (MetaFrames *frames,
guint32 timestamp);
static GdkRectangle* control_rect (MetaFrameControl control, static GdkRectangle* control_rect (MetaFrameControl control,
MetaFrameGeometry *fgeom); MetaFrameGeometry *fgeom);
@ -238,6 +224,7 @@ meta_frames_class_init (MetaFramesClass *class)
widget_class->button_press_event = meta_frames_button_press_event; widget_class->button_press_event = meta_frames_button_press_event;
widget_class->button_release_event = meta_frames_button_release_event; widget_class->button_release_event = meta_frames_button_release_event;
widget_class->motion_notify_event = meta_frames_motion_notify_event; widget_class->motion_notify_event = meta_frames_motion_notify_event;
widget_class->leave_notify_event = meta_frames_leave_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"));
@ -291,8 +278,6 @@ meta_frames_init (MetaFrames *frames)
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->tooltip_timeout = 0; frames->tooltip_timeout = 0;
frames->grab_status = META_FRAME_STATUS_NORMAL;
} }
static void static void
@ -711,55 +696,11 @@ meta_frames_manage_window (MetaFrames *frames,
/* Don't set event mask here, it's in frame.c */ /* Don't set event mask here, it's in frame.c */
/* Grab Alt + button1 and Alt + button2 for moving window,
* and Alt + button3 for popping up window menu.
*/
{
int i = 1;
while (i < 4)
{
int result;
gdk_error_trap_push ();
XGrabButton (gdk_display, i, Mod1Mask,
xwindow, False,
ButtonPressMask | ButtonReleaseMask |
PointerMotionMask | PointerMotionHintMask,
GrabModeAsync, GrabModeAsync,
False, None);
XSync (gdk_display, False);
result = gdk_error_trap_pop ();
if (result != Success)
meta_warning ("Failed to grab button %d with Mod1Mask for frame 0x%lx error code %d\n",
i, xwindow, result);
#if 1
/* This is just for debugging, since I end up moving
* the Xnest otherwise ;-)
*/
gdk_error_trap_push ();
result = XGrabButton (gdk_display, i, ControlMask,
xwindow, False,
ButtonPressMask | ButtonReleaseMask |
PointerMotionMask | PointerMotionHintMask,
GrabModeAsync, GrabModeAsync,
False, None);
XSync (gdk_display, False);
result = gdk_error_trap_pop ();
if (result != Success)
meta_warning ("Failed to grab button %d with ControlMask for frame 0x%lx error code %d\n",
i, xwindow, result);
#endif
++i;
}
}
frame->xwindow = xwindow; frame->xwindow = xwindow;
frame->layout = NULL; frame->layout = NULL;
meta_core_grab_buttons (gdk_display, frame->xwindow);
g_hash_table_insert (frames->frames, &frame->xwindow, frame); g_hash_table_insert (frames->frames, &frame->xwindow, frame);
} }
@ -780,9 +721,6 @@ meta_frames_unmanage_window (MetaFrames *frames,
if (frames->last_motion_frame == frame) if (frames->last_motion_frame == frame)
frames->last_motion_frame = NULL; frames->last_motion_frame = NULL;
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));
@ -803,12 +741,6 @@ meta_frames_realize (GtkWidget *widget)
frames = META_FRAMES (widget); frames = META_FRAMES (widget);
frames->south_resize_cursor = gdk_cursor_new (GDK_BOTTOM_SIDE);
frames->east_resize_cursor = gdk_cursor_new (GDK_RIGHT_SIDE);
frames->west_resize_cursor = gdk_cursor_new (GDK_LEFT_SIDE);
frames->se_resize_cursor = gdk_cursor_new (GDK_BOTTOM_RIGHT_CORNER);
frames->sw_resize_cursor = gdk_cursor_new (GDK_BOTTOM_LEFT_CORNER);
if (GTK_WIDGET_CLASS (parent_class)->realize) if (GTK_WIDGET_CLASS (parent_class)->realize)
GTK_WIDGET_CLASS (parent_class)->realize (widget); GTK_WIDGET_CLASS (parent_class)->realize (widget);
} }
@ -820,18 +752,6 @@ meta_frames_unrealize (GtkWidget *widget)
frames = META_FRAMES (widget); frames = META_FRAMES (widget);
gdk_cursor_unref (frames->south_resize_cursor);
gdk_cursor_unref (frames->east_resize_cursor);
gdk_cursor_unref (frames->west_resize_cursor);
gdk_cursor_unref (frames->se_resize_cursor);
gdk_cursor_unref (frames->sw_resize_cursor);
frames->south_resize_cursor = NULL;
frames->east_resize_cursor = NULL;
frames->west_resize_cursor = NULL;
frames->se_resize_cursor = NULL;
frames->sw_resize_cursor = NULL;
if (GTK_WIDGET_CLASS (parent_class)->unrealize) if (GTK_WIDGET_CLASS (parent_class)->unrealize)
GTK_WIDGET_CLASS (parent_class)->unrealize (widget); GTK_WIDGET_CLASS (parent_class)->unrealize (widget);
} }
@ -1039,258 +959,6 @@ clear_tip (MetaFrames *frames)
meta_fixed_tip_hide (); meta_fixed_tip_hide ();
} }
static GdkCursor*
cursor_for_resize (MetaFrames *frames,
MetaFrameStatus status)
{
GdkCursor *cursor;
cursor = NULL;
switch (status)
{
case META_FRAME_STATUS_RESIZING_E:
cursor = frames->east_resize_cursor;
break;
case META_FRAME_STATUS_RESIZING_W:
cursor = frames->west_resize_cursor;
break;
case META_FRAME_STATUS_RESIZING_S:
cursor = frames->south_resize_cursor;
break;
case META_FRAME_STATUS_RESIZING_SE:
cursor = frames->se_resize_cursor;
break;
case META_FRAME_STATUS_RESIZING_SW:
cursor = frames->sw_resize_cursor;
break;
case META_FRAME_STATUS_RESIZING_N:
case META_FRAME_STATUS_RESIZING_NE:
case META_FRAME_STATUS_RESIZING_NW:
break;
default:
g_assert_not_reached ();
break;
}
return cursor;
}
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,
int start_window_w,
int start_window_h,
guint32 timestamp)
{
GdkCursor *cursor;
g_return_if_fail (frames->grab_frame == NULL);
clear_tip (frames);
cursor = NULL;
switch (status)
{
case META_FRAME_STATUS_MOVING:
break;
case META_FRAME_STATUS_RESIZING_E:
case META_FRAME_STATUS_RESIZING_W:
case META_FRAME_STATUS_RESIZING_S:
case META_FRAME_STATUS_RESIZING_SE:
case META_FRAME_STATUS_RESIZING_SW:
case META_FRAME_STATUS_RESIZING_N:
case META_FRAME_STATUS_RESIZING_NE:
case META_FRAME_STATUS_RESIZING_NW:
cursor = cursor_for_resize (frames, status);
break;
case META_FRAME_STATUS_CLICKING_MINIMIZE:
break;
case META_FRAME_STATUS_CLICKING_MAXIMIZE:
break;
case META_FRAME_STATUS_CLICKING_DELETE:
break;
case META_FRAME_STATUS_CLICKING_MENU:
break;
case META_FRAME_STATUS_NORMAL:
break;
}
/* 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,
cursor,
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;
frames->start_window_w = start_window_w;
frames->start_window_h = start_window_h;
}
}
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);
}
static void
update_resize (MetaFrames *frames,
MetaUIFrame *frame,
MetaFrameStatus status,
int x, int y)
{
int dx, dy;
int new_w, new_h;
int gravity;
dx = x - frames->start_root_x;
dy = y - frames->start_root_y;
new_w = frames->start_window_w;
new_h = frames->start_window_h;
switch (status)
{
case META_FRAME_STATUS_RESIZING_SE:
case META_FRAME_STATUS_RESIZING_NE:
case META_FRAME_STATUS_RESIZING_E:
new_w += dx;
break;
case META_FRAME_STATUS_RESIZING_NW:
case META_FRAME_STATUS_RESIZING_SW:
case META_FRAME_STATUS_RESIZING_W:
new_w -= dx;
break;
default:
break;
}
switch (status)
{
case META_FRAME_STATUS_RESIZING_SE:
case META_FRAME_STATUS_RESIZING_S:
case META_FRAME_STATUS_RESIZING_SW:
new_h += dy;
break;
case META_FRAME_STATUS_RESIZING_N:
case META_FRAME_STATUS_RESIZING_NE:
case META_FRAME_STATUS_RESIZING_NW:
new_h -= dy;
break;
default:
break;
}
/* compute gravity of client during operation */
gravity = -1;
switch (status)
{
case META_FRAME_STATUS_RESIZING_SE:
gravity = NorthWestGravity;
break;
case META_FRAME_STATUS_RESIZING_S:
gravity = NorthGravity;
break;
case META_FRAME_STATUS_RESIZING_SW:
gravity = NorthEastGravity;
break;
case META_FRAME_STATUS_RESIZING_N:
gravity = SouthGravity;
break;
case META_FRAME_STATUS_RESIZING_NE:
gravity = SouthWestGravity;
break;
case META_FRAME_STATUS_RESIZING_NW:
gravity = SouthEastGravity;
break;
case META_FRAME_STATUS_RESIZING_E:
gravity = WestGravity;
break;
case META_FRAME_STATUS_RESIZING_W:
gravity = EastGravity;
break;
default:
g_assert_not_reached ();
break;
}
meta_core_user_resize (gdk_display, frame->xwindow, gravity, new_w, new_h);
}
static void static void
redraw_control (MetaFrames *frames, redraw_control (MetaFrames *frames,
MetaUIFrame *frame, MetaUIFrame *frame,
@ -1325,6 +993,10 @@ meta_frames_button_press_event (GtkWidget *widget,
frames = META_FRAMES (widget); frames = META_FRAMES (widget);
/* Remember that the display may have already done something with this event.
* If so there's probably a GrabOp in effect.
*/
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;
@ -1333,6 +1005,9 @@ meta_frames_button_press_event (GtkWidget *widget,
control = get_control (frames, frame, event->x, event->y); control = get_control (frames, frame, event->x, event->y);
/* We want to shade even if we have a GrabOp, since we'll have a move grab
* if we double click the titlebar.
*/
if (control == META_FRAME_CONTROL_TITLE && if (control == META_FRAME_CONTROL_TITLE &&
event->button == 1 && event->button == 1 &&
event->type == GDK_2BUTTON_PRESS) event->type == GDK_2BUTTON_PRESS)
@ -1354,52 +1029,50 @@ meta_frames_button_press_event (GtkWidget *widget,
return TRUE; return TRUE;
} }
if (frames->grab_frame != NULL) if (meta_core_get_grab_op (gdk_display) !=
META_GRAB_OP_NONE)
return FALSE; /* already up to something */ return FALSE; /* already up to something */
if (event->button == 1)
{
meta_core_user_raise (gdk_display, frame->xwindow);
meta_core_user_focus (gdk_display, frame->xwindow,
event->time);
}
if (event->button == 1 && if (event->button == 1 &&
(control == META_FRAME_CONTROL_MAXIMIZE || (control == META_FRAME_CONTROL_MAXIMIZE ||
control == META_FRAME_CONTROL_MINIMIZE || control == META_FRAME_CONTROL_MINIMIZE ||
control == META_FRAME_CONTROL_DELETE || control == META_FRAME_CONTROL_DELETE ||
control == META_FRAME_CONTROL_MENU)) control == META_FRAME_CONTROL_MENU))
{ {
MetaFrameStatus status = META_FRAME_STATUS_NORMAL; MetaGrabOp op = META_GRAB_OP_NONE;
switch (control) switch (control)
{ {
case META_FRAME_CONTROL_MINIMIZE: case META_FRAME_CONTROL_MINIMIZE:
status = META_FRAME_STATUS_CLICKING_MINIMIZE; op = META_GRAB_OP_CLICKING_MINIMIZE;
break; break;
case META_FRAME_CONTROL_MAXIMIZE: case META_FRAME_CONTROL_MAXIMIZE:
status = META_FRAME_STATUS_CLICKING_MAXIMIZE; op = META_GRAB_OP_CLICKING_MAXIMIZE;
break; break;
case META_FRAME_CONTROL_DELETE: case META_FRAME_CONTROL_DELETE:
status = META_FRAME_STATUS_CLICKING_DELETE; op = META_GRAB_OP_CLICKING_DELETE;
break; break;
case META_FRAME_CONTROL_MENU: case META_FRAME_CONTROL_MENU:
status = META_FRAME_STATUS_CLICKING_MENU; op = META_GRAB_OP_CLICKING_MENU;
break; break;
default: default:
g_assert_not_reached (); g_assert_not_reached ();
break; break;
} }
meta_frames_begin_grab (frames, frame, meta_core_begin_grab_op (gdk_display,
status, frame->xwindow,
op,
TRUE,
event->button, event->button,
0, 0, 0, 0, 0, 0, /* not needed */ 0,
event->time); event->time,
event->x_root,
event->y_root);
redraw_control (frames, frame, control); redraw_control (frames, frame, control);
if (status == META_FRAME_STATUS_CLICKING_MENU) if (op == META_GRAB_OP_CLICKING_MENU)
{ {
MetaFrameGeometry fgeom; MetaFrameGeometry fgeom;
GdkRectangle *rect; GdkRectangle *rect;
@ -1431,58 +1104,50 @@ meta_frames_button_press_event (GtkWidget *widget,
control == META_FRAME_CONTROL_RESIZE_E || control == META_FRAME_CONTROL_RESIZE_E ||
control == META_FRAME_CONTROL_RESIZE_W)) control == META_FRAME_CONTROL_RESIZE_W))
{ {
int w, h, x, y; MetaGrabOp op;
MetaFrameStatus status;
meta_core_get_size (gdk_display, op = META_GRAB_OP_NONE;
frame->xwindow,
&w, &h);
meta_core_get_position (gdk_display,
frame->xwindow,
&x, &y);
status = META_FRAME_STATUS_NORMAL;
switch (control) switch (control)
{ {
case META_FRAME_CONTROL_RESIZE_SE: case META_FRAME_CONTROL_RESIZE_SE:
status = META_FRAME_STATUS_RESIZING_SE; op = META_GRAB_OP_RESIZING_SE;
break; break;
case META_FRAME_CONTROL_RESIZE_S: case META_FRAME_CONTROL_RESIZE_S:
status = META_FRAME_STATUS_RESIZING_S; op = META_GRAB_OP_RESIZING_S;
break; break;
case META_FRAME_CONTROL_RESIZE_SW: case META_FRAME_CONTROL_RESIZE_SW:
status = META_FRAME_STATUS_RESIZING_SW; op = META_GRAB_OP_RESIZING_SW;
break; break;
case META_FRAME_CONTROL_RESIZE_NE: case META_FRAME_CONTROL_RESIZE_NE:
status = META_FRAME_STATUS_RESIZING_NE; op = META_GRAB_OP_RESIZING_NE;
break; break;
case META_FRAME_CONTROL_RESIZE_N: case META_FRAME_CONTROL_RESIZE_N:
status = META_FRAME_STATUS_RESIZING_N; op = META_GRAB_OP_RESIZING_N;
break; break;
case META_FRAME_CONTROL_RESIZE_NW: case META_FRAME_CONTROL_RESIZE_NW:
status = META_FRAME_STATUS_RESIZING_NW; op = META_GRAB_OP_RESIZING_NW;
break; break;
case META_FRAME_CONTROL_RESIZE_E: case META_FRAME_CONTROL_RESIZE_E:
status = META_FRAME_STATUS_RESIZING_E; op = META_GRAB_OP_RESIZING_E;
break; break;
case META_FRAME_CONTROL_RESIZE_W: case META_FRAME_CONTROL_RESIZE_W:
status = META_FRAME_STATUS_RESIZING_W; op = META_GRAB_OP_RESIZING_W;
break; break;
default: default:
g_assert_not_reached (); g_assert_not_reached ();
break; break;
} }
meta_frames_begin_grab (frames, frame, meta_core_begin_grab_op (gdk_display,
status, frame->xwindow,
op,
TRUE,
event->button, event->button,
0,
event->time,
event->x_root, event->x_root,
event->y_root, event->y_root);
x, y,
w, h,
event->time);
} }
else if (((control == META_FRAME_CONTROL_TITLE || else if (((control == META_FRAME_CONTROL_TITLE ||
control == META_FRAME_CONTROL_NONE) && control == META_FRAME_CONTROL_NONE) &&
@ -1495,23 +1160,15 @@ meta_frames_button_press_event (GtkWidget *widget,
if (flags & META_FRAME_ALLOWS_MOVE) if (flags & META_FRAME_ALLOWS_MOVE)
{ {
int x, y, w, h; meta_core_begin_grab_op (gdk_display,
meta_core_get_position (gdk_display,
frame->xwindow, frame->xwindow,
&x, &y); META_GRAB_OP_MOVING,
TRUE,
meta_core_get_size (gdk_display,
frame->xwindow,
&w, &h);
meta_frames_begin_grab (frames, frame,
META_FRAME_STATUS_MOVING,
event->button, event->button,
0,
event->time,
event->x_root, event->x_root,
event->y_root, event->y_root);
x, y, w, h,
event->time);
} }
} }
else if (event->button == 3) else if (event->button == 3)
@ -1530,11 +1187,26 @@ meta_frames_button_press_event (GtkWidget *widget,
void void
meta_frames_notify_menu_hide (MetaFrames *frames) meta_frames_notify_menu_hide (MetaFrames *frames)
{ {
if (frames->grab_status == META_FRAME_STATUS_CLICKING_MENU) if (meta_core_get_grab_op (gdk_display) ==
META_GRAB_OP_CLICKING_MENU)
{ {
redraw_control (frames, frames->grab_frame, Window grab_frame;
grab_frame = meta_core_get_grab_frame (gdk_display);
if (grab_frame != None)
{
MetaUIFrame *frame;
frame = meta_frames_lookup_window (frames, grab_frame);
if (frame)
{
redraw_control (frames, frame,
META_FRAME_CONTROL_MENU); META_FRAME_CONTROL_MENU);
meta_frames_end_grab (frames, GDK_CURRENT_TIME); meta_core_end_grab_op (gdk_display, CurrentTime);
}
}
} }
} }
@ -1544,6 +1216,7 @@ meta_frames_button_release_event (GtkWidget *widget,
{ {
MetaUIFrame *frame; MetaUIFrame *frame;
MetaFrames *frames; MetaFrames *frames;
MetaGrabOp op;
frames = META_FRAMES (widget); frames = META_FRAMES (widget);
@ -1553,33 +1226,25 @@ meta_frames_button_release_event (GtkWidget *widget,
clear_tip (frames); clear_tip (frames);
if (frames->grab_frame == frame && op = meta_core_get_grab_op (gdk_display);
frames->start_button == event->button)
if (op == META_GRAB_OP_NONE)
return FALSE;
/* We only handle the releases we handled the presses for (things
* involving frame controls). Window ops that don't require a
* frame are handled in the Xlib part of the code, display.c/window.c
*/
if (frame->xwindow == meta_core_get_grab_frame (gdk_display) &&
event->button == meta_core_get_grab_button (gdk_display))
{ {
MetaFrameStatus status; gboolean end_grab;
status = frames->grab_status; end_grab = FALSE;
meta_frames_end_grab (frames, event->time); switch (op)
switch (status)
{ {
case META_FRAME_STATUS_MOVING: case META_GRAB_OP_CLICKING_MINIMIZE:
update_move (frames, frame, event->x_root, event->y_root);
break;
case META_FRAME_STATUS_RESIZING_E:
case META_FRAME_STATUS_RESIZING_W:
case META_FRAME_STATUS_RESIZING_S:
case META_FRAME_STATUS_RESIZING_N:
case META_FRAME_STATUS_RESIZING_SE:
case META_FRAME_STATUS_RESIZING_SW:
case META_FRAME_STATUS_RESIZING_NE:
case META_FRAME_STATUS_RESIZING_NW:
update_resize (frames, frame, status, event->x_root, event->y_root);
break;
case META_FRAME_STATUS_CLICKING_MINIMIZE:
if (point_in_control (frames, frame, if (point_in_control (frames, frame,
META_FRAME_CONTROL_MINIMIZE, META_FRAME_CONTROL_MINIMIZE,
event->x, event->y)) event->x, event->y))
@ -1587,9 +1252,10 @@ meta_frames_button_release_event (GtkWidget *widget,
redraw_control (frames, frame, redraw_control (frames, frame,
META_FRAME_CONTROL_MINIMIZE); META_FRAME_CONTROL_MINIMIZE);
end_grab = TRUE;
break; break;
case META_FRAME_STATUS_CLICKING_MAXIMIZE: case META_GRAB_OP_CLICKING_MAXIMIZE:
if (point_in_control (frames, frame, if (point_in_control (frames, frame,
META_FRAME_CONTROL_MAXIMIZE, META_FRAME_CONTROL_MAXIMIZE,
event->x, event->y)) event->x, event->y))
@ -1602,25 +1268,31 @@ meta_frames_button_release_event (GtkWidget *widget,
} }
redraw_control (frames, frame, redraw_control (frames, frame,
META_FRAME_CONTROL_MAXIMIZE); META_FRAME_CONTROL_MAXIMIZE);
end_grab = TRUE;
break; break;
case META_FRAME_STATUS_CLICKING_DELETE: case META_GRAB_OP_CLICKING_DELETE:
if (point_in_control (frames, frame, if (point_in_control (frames, frame,
META_FRAME_CONTROL_DELETE, META_FRAME_CONTROL_DELETE,
event->x, event->y)) event->x, event->y))
meta_core_delete (gdk_display, frame->xwindow, event->time); meta_core_delete (gdk_display, frame->xwindow, event->time);
redraw_control (frames, frame, redraw_control (frames, frame,
META_FRAME_CONTROL_DELETE); META_FRAME_CONTROL_DELETE);
end_grab = TRUE;
break; break;
case META_FRAME_STATUS_CLICKING_MENU: case META_GRAB_OP_CLICKING_MENU:
redraw_control (frames, frame, redraw_control (frames, frame,
META_FRAME_CONTROL_MENU); META_FRAME_CONTROL_MENU);
end_grab = TRUE;
break; break;
case META_FRAME_STATUS_NORMAL: default:
break; break;
} }
if (end_grab)
meta_core_end_grab_op (gdk_display, event->time);
} }
return TRUE; return TRUE;
@ -1643,46 +1315,25 @@ meta_frames_motion_notify_event (GtkWidget *widget,
frames->last_motion_frame = frame; frames->last_motion_frame = frame;
switch (frames->grab_status) switch (meta_core_get_grab_op (gdk_display))
{ {
case META_FRAME_STATUS_MOVING: case META_GRAB_OP_CLICKING_MENU:
{ case META_GRAB_OP_CLICKING_DELETE:
int x, y; case META_GRAB_OP_CLICKING_MINIMIZE:
frame_query_root_pointer (frame, &x, &y); case META_GRAB_OP_CLICKING_MAXIMIZE:
update_move (frames, frame, x, y);
}
break;
case META_FRAME_STATUS_RESIZING_E:
case META_FRAME_STATUS_RESIZING_W:
case META_FRAME_STATUS_RESIZING_S:
case META_FRAME_STATUS_RESIZING_N:
case META_FRAME_STATUS_RESIZING_SE:
case META_FRAME_STATUS_RESIZING_SW:
case META_FRAME_STATUS_RESIZING_NE:
case META_FRAME_STATUS_RESIZING_NW:
{
int x, y;
frame_query_root_pointer (frame, &x, &y);
update_resize (frames, frame, frames->grab_status, x, y);
}
break; break;
case META_FRAME_STATUS_CLICKING_MENU: case META_GRAB_OP_NONE:
case META_FRAME_STATUS_CLICKING_DELETE:
case META_FRAME_STATUS_CLICKING_MINIMIZE:
case META_FRAME_STATUS_CLICKING_MAXIMIZE:
break;
case META_FRAME_STATUS_NORMAL:
{ {
MetaFrameControl control; MetaFrameControl control;
GdkCursor *cursor;
int x, y; int x, y;
MetaCursor cursor;
gdk_window_get_pointer (frame->window, &x, &y, NULL); gdk_window_get_pointer (frame->window, &x, &y, NULL);
control = get_control (frames, frame, x, y); control = get_control (frames, frame, x, y);
cursor = NULL; cursor = META_CURSOR_DEFAULT;
switch (control) switch (control)
{ {
@ -1699,37 +1350,42 @@ meta_frames_motion_notify_event (GtkWidget *widget,
case META_FRAME_CONTROL_MAXIMIZE: case META_FRAME_CONTROL_MAXIMIZE:
break; break;
case META_FRAME_CONTROL_RESIZE_SE: case META_FRAME_CONTROL_RESIZE_SE:
cursor = frames->se_resize_cursor; cursor = META_CURSOR_SE_RESIZE;
break; break;
case META_FRAME_CONTROL_RESIZE_S: case META_FRAME_CONTROL_RESIZE_S:
cursor = frames->south_resize_cursor; cursor = META_CURSOR_SOUTH_RESIZE;
break; break;
case META_FRAME_CONTROL_RESIZE_SW: case META_FRAME_CONTROL_RESIZE_SW:
cursor = frames->sw_resize_cursor; cursor = META_CURSOR_SW_RESIZE;
break; break;
case META_FRAME_CONTROL_RESIZE_N: case META_FRAME_CONTROL_RESIZE_N:
cursor = META_CURSOR_NORTH_RESIZE;
break; break;
case META_FRAME_CONTROL_RESIZE_NE: case META_FRAME_CONTROL_RESIZE_NE:
cursor = META_CURSOR_NE_RESIZE;
break; break;
case META_FRAME_CONTROL_RESIZE_NW: case META_FRAME_CONTROL_RESIZE_NW:
cursor = META_CURSOR_NW_RESIZE;
break; break;
case META_FRAME_CONTROL_RESIZE_W: case META_FRAME_CONTROL_RESIZE_W:
cursor = frames->west_resize_cursor; cursor = META_CURSOR_WEST_RESIZE;
break; break;
case META_FRAME_CONTROL_RESIZE_E: case META_FRAME_CONTROL_RESIZE_E:
cursor = frames->east_resize_cursor; cursor = META_CURSOR_EAST_RESIZE;
break; break;
} }
if (cursor != frames->current_cursor) /* set/unset the prelight cursor */
{ meta_core_set_screen_cursor (gdk_display,
gdk_window_set_cursor (frame->window, cursor); frame->xwindow,
frames->current_cursor = cursor; cursor);
}
queue_tip (frames); queue_tip (frames);
} }
break; break;
default:
break;
} }
return TRUE; return TRUE;
@ -1748,9 +1404,6 @@ 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;
} }
@ -1890,23 +1543,26 @@ draw_control_bg (MetaFrames *frames,
GdkRectangle *rect; GdkRectangle *rect;
GtkWidget *widget; GtkWidget *widget;
gboolean draw = FALSE; gboolean draw = FALSE;
Window grab_frame;
widget = GTK_WIDGET (frames); widget = GTK_WIDGET (frames);
if (frame == frames->grab_frame) grab_frame = meta_core_get_grab_frame (gdk_display);
if (frame->xwindow == grab_frame)
{ {
switch (frames->grab_status) switch (meta_core_get_grab_op (gdk_display))
{ {
case META_FRAME_STATUS_CLICKING_MENU: case META_GRAB_OP_CLICKING_MENU:
draw = control == META_FRAME_CONTROL_MENU; draw = control == META_FRAME_CONTROL_MENU;
break; break;
case META_FRAME_STATUS_CLICKING_DELETE: case META_GRAB_OP_CLICKING_DELETE:
draw = control == META_FRAME_CONTROL_DELETE; draw = control == META_FRAME_CONTROL_DELETE;
break; break;
case META_FRAME_STATUS_CLICKING_MAXIMIZE: case META_GRAB_OP_CLICKING_MAXIMIZE:
draw = control == META_FRAME_CONTROL_MAXIMIZE; draw = control == META_FRAME_CONTROL_MAXIMIZE;
break; break;
case META_FRAME_STATUS_CLICKING_MINIMIZE: case META_GRAB_OP_CLICKING_MINIMIZE:
draw = control == META_FRAME_CONTROL_MINIMIZE; draw = control == META_FRAME_CONTROL_MINIMIZE;
break; break;
default: default:
@ -2169,11 +1825,11 @@ meta_frames_leave_notify_event (GtkWidget *widget,
if (frame == NULL) if (frame == NULL)
return FALSE; return FALSE;
if (frames->current_cursor) clear_tip (frames);
{
gdk_window_set_cursor (frame->window, NULL); meta_core_set_screen_cursor (gdk_display,
frames->current_cursor = NULL; frame->xwindow,
} META_CURSOR_DEFAULT);
return TRUE; return TRUE;
} }
@ -2255,9 +1911,6 @@ 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;
} }
@ -2309,9 +1962,6 @@ meta_frames_window_state_event (GtkWidget *widget,
return TRUE; return TRUE;
} }
static GdkRectangle* static GdkRectangle*
control_rect (MetaFrameControl control, control_rect (MetaFrameControl control,
MetaFrameGeometry *fgeom) MetaFrameGeometry *fgeom)
@ -2447,13 +2097,3 @@ get_control (MetaFrames *frames,
return META_FRAME_CONTROL_NONE; return META_FRAME_CONTROL_NONE;
} }
Window
meta_frames_get_moving_frame (MetaFrames *frames)
{
if (frames->grab_frame &&
frames->grab_status == META_FRAME_STATUS_MOVING)
return frames->grab_frame->xwindow;
else
return None;
}

View File

@ -44,24 +44,6 @@ typedef enum
META_FRAME_CONTROL_RESIZE_E META_FRAME_CONTROL_RESIZE_E
} MetaFrameControl; } MetaFrameControl;
typedef enum
{
META_FRAME_STATUS_NORMAL,
META_FRAME_STATUS_MOVING,
META_FRAME_STATUS_CLICKING_MINIMIZE,
META_FRAME_STATUS_CLICKING_MAXIMIZE,
META_FRAME_STATUS_CLICKING_DELETE,
META_FRAME_STATUS_CLICKING_MENU,
META_FRAME_STATUS_RESIZING_SE,
META_FRAME_STATUS_RESIZING_S,
META_FRAME_STATUS_RESIZING_SW,
META_FRAME_STATUS_RESIZING_N,
META_FRAME_STATUS_RESIZING_NE,
META_FRAME_STATUS_RESIZING_NW,
META_FRAME_STATUS_RESIZING_W,
META_FRAME_STATUS_RESIZING_E
} 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.
*/ */
@ -99,26 +81,6 @@ struct _MetaFrames
guint tooltip_timeout; guint tooltip_timeout;
MetaUIFrame *last_motion_frame; MetaUIFrame *last_motion_frame;
GdkCursor *south_resize_cursor;
GdkCursor *west_resize_cursor;
GdkCursor *east_resize_cursor;
GdkCursor *se_resize_cursor;
GdkCursor *sw_resize_cursor;
GdkCursor *current_cursor;
/* 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 position for drags */
int start_window_x, start_window_y;
/* initial window size for drags */
int start_window_w, start_window_h;
/* button doing the dragging */
int start_button;
}; };
struct _MetaFramesClass struct _MetaFramesClass

View File

@ -408,7 +408,7 @@ meta_display_process_key_event (MetaDisplay *display,
return; /* don't care about releases */ return; /* don't care about releases */
if (window == NULL) if (window == NULL)
meta_bug ("NULL window while META_GRAB_OP_MOVING\n"); meta_bug ("NULL window while doing keyboard grab op\n");
meta_window_get_position (window, &x, &y); meta_window_get_position (window, &x, &y);
@ -512,20 +512,14 @@ handle_activate_workspace (MetaDisplay *display,
if (workspace) if (workspace)
{ {
Window move_frame;
MetaWindow *move_window; MetaWindow *move_window;
move_window = NULL; move_window = NULL;
move_frame = meta_ui_get_moving_frame (workspace->screen->ui); if (display->grab_op == META_GRAB_OP_MOVING)
move_window = display->grab_window;
if (move_frame != None) if (move_window != NULL)
{ {
move_window = meta_display_lookup_x_window (display, move_frame);
if (move_window == NULL ||
move_window->frame == NULL)
meta_bug ("No move_frame window 0x%lx!\n", move_frame);
if (move_window->on_all_workspaces) if (move_window->on_all_workspaces)
move_window = NULL; /* don't move it after all */ move_window = NULL; /* don't move it after all */

View File

@ -28,7 +28,6 @@
#include "keybindings.h" #include "keybindings.h"
#include "stack.h" #include "stack.h"
#include <X11/cursorfont.h>
#include <X11/Xatom.h> #include <X11/Xatom.h>
#include <locale.h> #include <locale.h>
#include <string.h> #include <string.h>
@ -113,7 +112,6 @@ meta_screen_new (MetaDisplay *display,
MetaScreen *screen; MetaScreen *screen;
Window xroot; Window xroot;
Display *xdisplay; Display *xdisplay;
Cursor cursor;
/* Only display->name, display->xdisplay, and display->error_traps /* Only display->name, display->xdisplay, and display->error_traps
* can really be used in this function, since normally screens are * can really be used in this function, since normally screens are
@ -152,10 +150,6 @@ meta_screen_new (MetaDisplay *display,
return NULL; return NULL;
} }
cursor = XCreateFontCursor (display->xdisplay, XC_left_ptr);
XDefineCursor (display->xdisplay, xroot, cursor);
XFreeCursor (display->xdisplay, cursor);
screen = g_new (MetaScreen, 1); screen = g_new (MetaScreen, 1);
screen->display = display; screen->display = display;
@ -165,6 +159,9 @@ meta_screen_new (MetaDisplay *display,
screen->xroot = xroot; screen->xroot = xroot;
screen->width = WidthOfScreen (screen->xscreen); screen->width = WidthOfScreen (screen->xscreen);
screen->height = HeightOfScreen (screen->xscreen); screen->height = HeightOfScreen (screen->xscreen);
screen->current_cursor = -1; /* invalid/unset */
meta_screen_set_cursor (screen, META_CURSOR_DEFAULT);
if (display->leader_window == None) if (display->leader_window == None)
display->leader_window = XCreateSimpleWindow (display->xdisplay, display->leader_window = XCreateSimpleWindow (display->xdisplay,
@ -400,3 +397,19 @@ meta_screen_get_n_workspaces (MetaScreen *screen)
return i; return i;
} }
void
meta_screen_set_cursor (MetaScreen *screen,
MetaCursor cursor)
{
Cursor xcursor;
if (cursor == screen->current_cursor)
return;
screen->current_cursor = cursor;
xcursor = meta_display_create_x_cursor (screen->display, cursor);
XDefineCursor (screen->display->xdisplay, screen->xroot, xcursor);
XFreeCursor (screen->display->xdisplay, xcursor);
}

View File

@ -43,6 +43,8 @@ struct _MetaScreen
MetaWorkspace *active_workspace; MetaWorkspace *active_workspace;
MetaStack *stack; MetaStack *stack;
MetaCursor current_cursor;
}; };
MetaScreen* meta_screen_new (MetaDisplay *display, MetaScreen* meta_screen_new (MetaDisplay *display,
@ -58,6 +60,8 @@ void meta_screen_queue_window_resizes (MetaScreen *scre
int meta_screen_get_n_workspaces (MetaScreen *screen); int meta_screen_get_n_workspaces (MetaScreen *screen);
void meta_screen_set_cursor (MetaScreen *screen,
MetaCursor cursor);
#endif #endif

View File

@ -151,12 +151,6 @@ meta_ui_remove_frame (MetaUI *ui,
meta_frames_unmanage_window (ui->frames, xwindow); meta_frames_unmanage_window (ui->frames, xwindow);
} }
Window
meta_ui_get_moving_frame (MetaUI *ui)
{
return meta_frames_get_moving_frame (ui->frames);
}
void void
meta_ui_map_frame (MetaUI *ui, meta_ui_map_frame (MetaUI *ui,
Window xwindow) Window xwindow)

View File

@ -55,8 +55,6 @@ void meta_ui_add_frame (MetaUI *ui,
void meta_ui_remove_frame (MetaUI *ui, void meta_ui_remove_frame (MetaUI *ui,
Window xwindow); Window xwindow);
Window meta_ui_get_moving_frame (MetaUI *ui);
/* GDK insists on tracking map/unmap */ /* GDK insists on tracking map/unmap */
void meta_ui_map_frame (MetaUI *ui, void meta_ui_map_frame (MetaUI *ui,

View File

@ -2876,7 +2876,7 @@ update_sm_hints (MetaWindow *window)
window->display->atom_sm_client_id, window->display->atom_sm_client_id,
&window->sm_client_id); &window->sm_client_id);
meta_verbose ("Window %s client leader: 0x%ld SM_CLIENT_ID: '%s'\n", meta_verbose ("Window %s client leader: 0x%lx SM_CLIENT_ID: '%s'\n",
window->desc, window->xclient_leader, window->sm_client_id); window->desc, window->xclient_leader, window->sm_client_id);
} }
else else
@ -2915,7 +2915,7 @@ update_transient_for (MetaWindow *window)
window->xtransient_for = w; window->xtransient_for = w;
if (window->xtransient_for != None) if (window->xtransient_for != None)
meta_verbose ("Window %s transient for 0x%ld\n", window->desc, meta_verbose ("Window %s transient for 0x%lx\n", window->desc,
window->xtransient_for); window->xtransient_for);
else else
meta_verbose ("Window %s is not transient\n", window->desc); meta_verbose ("Window %s is not transient\n", window->desc);

View File

@ -297,4 +297,7 @@ gboolean meta_window_shares_some_workspace (MetaWindow *window,
void meta_window_set_gravity (MetaWindow *window, void meta_window_set_gravity (MetaWindow *window,
int gravity); int gravity);
void meta_window_handle_mouse_grab_op_event (MetaWindow *window,
XEvent *event);
#endif #endif