diff --git a/configure.in b/configure.in index 7150d9236..87bcea717 100644 --- a/configure.in +++ b/configure.in @@ -73,7 +73,6 @@ Makefile intl/Makefile po/Makefile.in src/Makefile -src/uislave/Makefile ]) diff --git a/src/.cvsignore b/src/.cvsignore index 37889d6a1..7328bed54 100644 --- a/src/.cvsignore +++ b/src/.cvsignore @@ -3,5 +3,3 @@ Makefile.in Makefile .deps metacity -messagequeue.h -messagequeue.c diff --git a/src/Makefile.am b/src/Makefile.am index d86915a0e..6b1771042 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -10,6 +10,8 @@ metacity_SOURCES= \ errors.h \ eventqueue.c \ eventqueue.h \ + fixedtip.c \ + fixedtip.h \ frame.c \ frame.h \ frames.c \ diff --git a/src/core.c b/src/core.c index c1b856af1..f3275a245 100644 --- a/src/core.c +++ b/src/core.c @@ -98,6 +98,7 @@ meta_core_user_move (Display *xdisplay, void meta_core_user_resize (Display *xdisplay, Window frame_xwindow, + int gravity, int width, int height) { @@ -111,7 +112,7 @@ meta_core_user_resize (Display *xdisplay, meta_bug ("No such frame window 0x%lx!\n", frame_xwindow); window->user_has_resized = TRUE; - meta_window_resize (window, width, height); + meta_window_resize_with_gravity (window, width, height, gravity); } void @@ -375,4 +376,3 @@ meta_core_show_window_menu (Display *xdisplay, meta_window_show_menu (window, root_x, root_y, button, timestamp); } - diff --git a/src/core.h b/src/core.h index e6c3bcc67..327c87a71 100644 --- a/src/core.h +++ b/src/core.h @@ -46,6 +46,7 @@ void meta_core_user_move (Display *xdisplay, int y); void meta_core_user_resize (Display *xdisplay, Window frame_xwindow, + int gravity, int width, int height); @@ -84,7 +85,6 @@ void meta_core_change_workspace (Display *xdisplay, Window frame_xwindow, int new_workspace); - int meta_core_get_num_workspaces (Screen *xscreen); int meta_core_get_active_workspace (Screen *xscreen); int meta_core_get_frame_workspace (Display *xdisplay, diff --git a/src/fixedtip.c b/src/fixedtip.c index bb12e405b..fb016a34e 100644 --- a/src/fixedtip.c +++ b/src/fixedtip.c @@ -36,7 +36,8 @@ expose_handler (GtkTooltips *tooltips) } void -meta_fixed_tip_show (int root_x, int root_y, +meta_fixed_tip_show (Display *xdisplay, + int root_x, int root_y, const char *markup_text) { if (tip == NULL) @@ -74,5 +75,9 @@ meta_fixed_tip_show (int root_x, int root_y, void meta_fixed_tip_hide (void) { - gtk_widget_destroy (tip); + if (tip) + { + gtk_widget_destroy (tip); + tip = NULL; + } } diff --git a/src/fixedtip.h b/src/fixedtip.h index 4b637fc6e..9f167b08e 100644 --- a/src/fixedtip.h +++ b/src/fixedtip.h @@ -23,8 +23,10 @@ #define META_FIXED_TIP_H #include +#include -void meta_fixed_tip_show (int root_x, int root_y, +void meta_fixed_tip_show (Display *xdisplay, + int root_x, int root_y, const char *markup_text); void meta_fixed_tip_hide (void); diff --git a/src/frames.c b/src/frames.c index 0c82a501a..bbe80ab5f 100644 --- a/src/frames.c +++ b/src/frames.c @@ -23,6 +23,7 @@ #include "util.h" #include "core.h" #include "menu.h" +#include "fixedtip.h" #define DEFAULT_INNER_BUTTON_BORDER 3 @@ -141,6 +142,8 @@ static void meta_frames_begin_grab (MetaFrames *frames, 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); @@ -152,6 +155,7 @@ static MetaFrameControl get_control (MetaFrames *frames, MetaUIFrame *frame, int x, int y); +static void clear_tip (MetaFrames *frames); enum { @@ -280,6 +284,8 @@ meta_frames_init (MetaFrames *frames) frames->frames = g_hash_table_new (unsigned_long_hash, unsigned_long_equal); + frames->tooltip_timeout = 0; + frames->grab_status = META_FRAME_STATUS_NORMAL; } @@ -300,6 +306,8 @@ meta_frames_destroy (GtkObject *object) MetaFrames *frames; frames = META_FRAMES (object); + + clear_tip (frames); winlist = NULL; g_hash_table_foreach (frames->frames, @@ -730,11 +738,16 @@ meta_frames_unmanage_window (MetaFrames *frames, { MetaUIFrame *frame; + clear_tip (frames); + frame = g_hash_table_lookup (frames->frames, &xwindow); if (frame) - { + { gdk_window_set_user_data (frame->window, NULL); + + if (frames->last_motion_frame == frame) + frames->last_motion_frame = NULL; if (frames->grab_frame == frame) meta_frames_end_grab (frames, GDK_CURRENT_TIME); @@ -839,6 +852,122 @@ meta_frames_set_title (MetaFrames *frames, gdk_window_invalidate_rect (frame->window, NULL, FALSE); } + +static void +show_tip_now (MetaFrames *frames) +{ + const char *tiptext; + MetaUIFrame *frame; + int x, y, root_x, root_y; + Window root, child; + guint mask; + MetaFrameControl control; + + frame = frames->last_motion_frame; + if (frame == NULL) + return; + + XQueryPointer (gdk_display, + frame->xwindow, + &root, &child, + &root_x, &root_y, + &x, &y, + &mask); + + control = get_control (frames, frame, x, y); + + tiptext = NULL; + switch (control) + { + case META_FRAME_CONTROL_TITLE: + break; + case META_FRAME_CONTROL_DELETE: + tiptext = _("Close Window"); + break; + case META_FRAME_CONTROL_MENU: + tiptext = _("Window Menu"); + break; + case META_FRAME_CONTROL_MINIMIZE: + tiptext = _("Minimize Window"); + break; + case META_FRAME_CONTROL_MAXIMIZE: + tiptext = _("Maximize Window"); + 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; + } + + if (tiptext) + { + MetaFrameGeometry fgeom; + GdkRectangle *rect; + int dx, dy; + + meta_frames_calc_geometry (frames, frame, &fgeom); + + rect = control_rect (control, &fgeom); + + /* get conversion delta for root-to-frame coords */ + dx = root_x - x; + dy = root_y - y; + + meta_fixed_tip_show (gdk_display, + rect->x + dx, + rect->y + rect->height + 2 + dy, + tiptext); + } +} + +static gboolean +tip_timeout_func (gpointer data) +{ + MetaFrames *frames; + + frames = data; + + show_tip_now (frames); + + return FALSE; +} + +#define TIP_DELAY 450 +static void +queue_tip (MetaFrames *frames) +{ + clear_tip (frames); + + frames->tooltip_timeout = g_timeout_add (TIP_DELAY, + tip_timeout_func, + frames); +} + +static void +clear_tip (MetaFrames *frames) +{ + if (frames->tooltip_timeout) + { + g_source_remove (frames->tooltip_timeout); + frames->tooltip_timeout = 0; + } + meta_fixed_tip_hide (); +} + static void meta_frames_begin_grab (MetaFrames *frames, MetaUIFrame *frame, @@ -848,10 +977,14 @@ meta_frames_begin_grab (MetaFrames *frames, int start_root_y, int start_window_x, int start_window_y, + int start_window_w, + int start_window_h, guint32 timestamp) { g_return_if_fail (frames->grab_frame == NULL); + clear_tip (frames); + /* This grab isn't needed I don't think */ if (gdk_pointer_grab (frame->window, FALSE, @@ -868,6 +1001,8 @@ meta_frames_begin_grab (MetaFrames *frames, 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; } } @@ -926,19 +1061,90 @@ update_move (MetaFrames *frames, } static void -update_resize_se (MetaFrames *frames, - MetaUIFrame *frame, - int x, int y) +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; - meta_core_user_resize (gdk_display, - frame->xwindow, - frames->start_window_x + dx, - frames->start_window_y + dy); + 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 @@ -978,6 +1184,8 @@ meta_frames_button_press_event (GtkWidget *widget, frame = meta_frames_lookup_window (frames, GDK_WINDOW_XID (event->window)); if (frame == NULL) return FALSE; + + clear_tip (frames); control = get_control (frames, frame, event->x, event->y); @@ -1040,23 +1248,42 @@ meta_frames_button_press_event (GtkWidget *widget, meta_frames_begin_grab (frames, frame, status, event->button, - 0, 0, 0, 0, /* not needed */ + 0, 0, 0, 0, 0, 0, /* not needed */ event->time); redraw_control (frames, frame, control); if (status == META_FRAME_STATUS_CLICKING_MENU) { + MetaFrameGeometry fgeom; + GdkRectangle *rect; + int dx, dy; + + meta_frames_calc_geometry (frames, frame, &fgeom); + + rect = control_rect (META_FRAME_CONTROL_MENU, &fgeom); + + /* get delta to convert to root coords */ + dx = event->x_root - event->x; + dy = event->y_root - event->y; + meta_core_show_window_menu (gdk_display, frame->xwindow, - event->x_root, - event->y_root, + rect->x + dx, + rect->y + rect->height + dy, event->button, event->time); } } - else if (control == META_FRAME_CONTROL_RESIZE_SE && - event->button == 1) + else if (event->button == 1 && + (control == META_FRAME_CONTROL_RESIZE_SE || + control == META_FRAME_CONTROL_RESIZE_S || + control == META_FRAME_CONTROL_RESIZE_SW || + control == META_FRAME_CONTROL_RESIZE_NE || + control == META_FRAME_CONTROL_RESIZE_N || + control == META_FRAME_CONTROL_RESIZE_NW || + control == META_FRAME_CONTROL_RESIZE_E || + control == META_FRAME_CONTROL_RESIZE_W)) { MetaFrameFlags flags; @@ -1064,17 +1291,56 @@ meta_frames_button_press_event (GtkWidget *widget, if (flags & META_FRAME_ALLOWS_RESIZE) { - int w, h; + int w, h, x, y; + MetaFrameStatus status; meta_core_get_size (gdk_display, frame->xwindow, &w, &h); + + meta_core_get_position (gdk_display, + frame->xwindow, + &x, &y); + + status = META_FRAME_STATUS_NORMAL; + + switch (control) + { + case META_FRAME_CONTROL_RESIZE_SE: + status = META_FRAME_STATUS_RESIZING_SE; + break; + case META_FRAME_CONTROL_RESIZE_S: + status = META_FRAME_STATUS_RESIZING_S; + break; + case META_FRAME_CONTROL_RESIZE_SW: + status = META_FRAME_STATUS_RESIZING_SW; + break; + case META_FRAME_CONTROL_RESIZE_NE: + status = META_FRAME_STATUS_RESIZING_NE; + break; + case META_FRAME_CONTROL_RESIZE_N: + status = META_FRAME_STATUS_RESIZING_N; + break; + case META_FRAME_CONTROL_RESIZE_NW: + status = META_FRAME_STATUS_RESIZING_NW; + break; + case META_FRAME_CONTROL_RESIZE_E: + status = META_FRAME_STATUS_RESIZING_E; + break; + case META_FRAME_CONTROL_RESIZE_W: + status = META_FRAME_STATUS_RESIZING_W; + break; + default: + g_assert_not_reached (); + break; + } meta_frames_begin_grab (frames, frame, - META_FRAME_STATUS_RESIZING_SE, + status, event->button, event->x_root, event->y_root, + x, y, w, h, event->time); } @@ -1090,18 +1356,22 @@ meta_frames_button_press_event (GtkWidget *widget, if (flags & META_FRAME_ALLOWS_MOVE) { - int x, y; + int x, y, w, h; meta_core_get_position (gdk_display, frame->xwindow, &x, &y); + + meta_core_get_size (gdk_display, + frame->xwindow, + &w, &h); meta_frames_begin_grab (frames, frame, META_FRAME_STATUS_MOVING, event->button, event->x_root, event->y_root, - x, y, + x, y, w, h, event->time); } } @@ -1133,6 +1403,8 @@ meta_frames_button_release_event (GtkWidget *widget, if (frame == NULL) return FALSE; + clear_tip (frames); + if (frames->grab_frame == frame && frames->start_button == event->button) { @@ -1147,9 +1419,16 @@ meta_frames_button_release_event (GtkWidget *widget, case META_FRAME_STATUS_MOVING: 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: - update_resize_se (frames, frame, event->x_root, event->y_root); + 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: @@ -1207,11 +1486,15 @@ meta_frames_motion_notify_event (GtkWidget *widget, MetaFrames *frames; frames = META_FRAMES (widget); - + frame = meta_frames_lookup_window (frames, GDK_WINDOW_XID (event->window)); if (frame == NULL) return FALSE; + clear_tip (frames); + + frames->last_motion_frame = frame; + switch (frames->grab_status) { case META_FRAME_STATUS_MOVING: @@ -1221,11 +1504,18 @@ meta_frames_motion_notify_event (GtkWidget *widget, 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_se (frames, frame, x, y); + update_resize (frames, frame, frames->grab_status, x, y); } break; @@ -1233,7 +1523,9 @@ meta_frames_motion_notify_event (GtkWidget *widget, case META_FRAME_STATUS_CLICKING_DELETE: case META_FRAME_STATUS_CLICKING_MINIMIZE: case META_FRAME_STATUS_CLICKING_MAXIMIZE: + break; case META_FRAME_STATUS_NORMAL: + queue_tip (frames); break; } @@ -1864,7 +2156,7 @@ control_rect (MetaFrameControl control, (ycoord) >= (rect).y && \ (ycoord) < ((rect).y + (rect).height)) -#define RESIZE_EXTENDS 10 +#define RESIZE_EXTENDS 15 static MetaFrameControl get_control (MetaFrames *frames, MetaUIFrame *frame, @@ -1889,619 +2181,18 @@ get_control (MetaFrames *frames, 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)) + if (y >= (fgeom.height - fgeom.bottom_height - RESIZE_EXTENDS) && + x >= (fgeom.width - fgeom.right_width - RESIZE_EXTENDS)) return META_FRAME_CONTROL_RESIZE_SE; + else if (y >= (fgeom.height - fgeom.bottom_height - RESIZE_EXTENDS) && + x <= (fgeom.left_width + RESIZE_EXTENDS)) + return META_FRAME_CONTROL_RESIZE_SW; + else if (y >= (fgeom.height - fgeom.bottom_height - RESIZE_EXTENDS)) + return META_FRAME_CONTROL_RESIZE_S; + else if (x <= fgeom.left_width) + return META_FRAME_CONTROL_RESIZE_W; + else if (x >= (fgeom.width - fgeom.right_width)) + return META_FRAME_CONTROL_RESIZE_E; return META_FRAME_CONTROL_NONE; } - - - - - - - - - - - - - - - - - - -#if 0 - -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 (frame->window->display->xdisplay, - 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 -show_tip_now (MetaUIFrame *frame) -{ - const char *tiptext; - - tiptext = NULL; - switch (frame->current_control) - { - case META_FRAME_CONTROL_TITLE: - break; - case META_FRAME_CONTROL_DELETE: - tiptext = _("Close Window"); - break; - case META_FRAME_CONTROL_MENU: - tiptext = _("Menu"); - break; - case META_FRAME_CONTROL_ICONIFY: - tiptext = _("Minimize Window"); - break; - case META_FRAME_CONTROL_MAXIMIZE: - tiptext = _("Maximize Window"); - 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; - } - - if (tiptext) - { - int x, y, width, height; - MetaFrameInfo info; - - meta_frame_init_info (frame, &info); - frame->window->screen->engine->get_control_rect (&info, - frame->current_control, - &x, &y, &width, &height, - frame->theme_data); - - /* Display tip a couple pixels below control */ - meta_screen_show_tip (frame->window->screen, - frame->rect.x + x, - frame->rect.y + y + height + 2, - tiptext); - } -} - -static gboolean -tip_timeout_func (gpointer data) -{ - MetaUIFrame *frame; - - frame = data; - - show_tip_now (frame); - - return FALSE; -} - -#define TIP_DELAY 250 -static void -queue_tip (MetaUIFrame *frame) -{ - if (frame->tooltip_timeout) - g_source_remove (frame->tooltip_timeout); - - frame->tooltip_timeout = g_timeout_add (250, - tip_timeout_func, - frame); -} - -static void -clear_tip (MetaUIFrame *frame) -{ - if (frame->tooltip_timeout) - { - g_source_remove (frame->tooltip_timeout); - frame->tooltip_timeout = 0; - } - meta_screen_hide_tip (frame->window->screen); -} - -static MetaFrameControl -frame_get_control (MetaUIFrame *frame, - int x, int y) -{ - MetaFrameInfo info; - - if (x < 0 || y < 0 || - x > frame->rect.width || y > frame->rect.height) - return META_FRAME_CONTROL_NONE; - - meta_frame_init_info (frame, &info); - - return frame->window->screen->engine->get_control (&info, - x, y, - frame->theme_data); -} - -static void -update_move (MetaUIFrame *frame, - int x, - int y) -{ - int dx, dy; - - dx = x - frame->grab->start_root_x; - dy = y - frame->grab->start_root_y; - - frame->window->user_has_moved = TRUE; - meta_window_move (frame->window, - frame->grab->start_window_x + dx, - frame->grab->start_window_y + dy); -} - -static void -update_resize_se (MetaUIFrame *frame, - int x, int y) -{ - int dx, dy; - - dx = x - frame->grab->start_root_x; - dy = y - frame->grab->start_root_y; - - frame->window->user_has_resized = TRUE; - meta_window_resize (frame->window, - frame->grab->start_window_x + dx, - frame->grab->start_window_y + dy); -} - -static void -update_current_control (MetaUIFrame *frame, - int x_root, int y_root) -{ - MetaFrameControl old; - - if (frame->grab) - return; - - old = frame->current_control; - - frame->current_control = frame_get_control (frame, - x_root - frame->rect.x, - y_root - frame->rect.y); - - if (old != frame->current_control) - { - meta_frame_queue_draw (frame); - - if (frame->current_control == META_FRAME_CONTROL_NONE) - clear_tip (frame); - else - queue_tip (frame); - } -} - -static void -grab_action (MetaUIFrame *frame, - MetaFrameAction action, - Time time) -{ - meta_verbose ("Grabbing action %d\n", action); - - frame->grab = g_new0 (MetaFrameActionGrab, 1); - - if (XGrabPointer (frame->window->display->xdisplay, - frame->xwindow, - False, - ButtonPressMask | ButtonReleaseMask | - PointerMotionMask | PointerMotionHintMask, - GrabModeAsync, GrabModeAsync, - None, - None, - time) != GrabSuccess) - meta_warning ("Grab for frame action failed\n"); - - frame->grab->action = action; - - /* display ACTIVE state */ - meta_frame_queue_draw (frame); - - clear_tip (frame); -} - -static void -ungrab_action (MetaUIFrame *frame, - Time time) -{ - int x, y; - - meta_verbose ("Ungrabbing action %d\n", frame->grab->action); - - XUngrabPointer (frame->window->display->xdisplay, - time); - - g_free (frame->grab); - frame->grab = NULL; - - frame_query_root_pointer (frame, &x, &y); - update_current_control (frame, x, y); - - /* undisplay ACTIVE state */ - meta_frame_queue_draw (frame); - - queue_tip (frame); -} - -static void -get_menu_items (MetaUIFrame *frame, - MetaFrameInfo *info, - MetaMessageWindowMenuOps *ops, - MetaMessageWindowMenuOps *insensitive) -{ - *ops = 0; - *insensitive = 0; - - if (info->flags & META_FRAME_CONTROL_MAXIMIZE) - { - if (frame->window->maximized) - *ops |= META_MESSAGE_MENU_UNMAXIMIZE; - else - *ops |= META_MESSAGE_MENU_MAXIMIZE; - } - - if (frame->window->shaded) - *ops |= META_MESSAGE_MENU_UNSHADE; - else - *ops |= META_MESSAGE_MENU_SHADE; - - if (frame->window->on_all_workspaces) - *ops |= META_MESSAGE_MENU_UNSTICK; - else - *ops |= META_MESSAGE_MENU_STICK; - - *ops |= (META_MESSAGE_MENU_DELETE | META_MESSAGE_MENU_WORKSPACES | META_MESSAGE_MENU_MINIMIZE); - - if (!(info->flags & META_FRAME_CONTROL_ICONIFY)) - *insensitive |= META_MESSAGE_MENU_MINIMIZE; - - if (!(info->flags & META_FRAME_CONTROL_DELETE)) - *insensitive |= META_MESSAGE_MENU_DELETE; -} - -gboolean -meta_frame_event (MetaUIFrame *frame, - XEvent *event) -{ - switch (event->type) - { - case KeyPress: - break; - case KeyRelease: - break; - case ButtonPress: - /* you can use button 2 to move a window without raising it */ - if (event->xbutton.button == 1) - meta_window_raise (frame->window); - - update_current_control (frame, - event->xbutton.x_root, - event->xbutton.y_root); - - if (frame->grab == NULL) - { - MetaFrameControl control; - control = frame->current_control; - - if (control == META_FRAME_CONTROL_TITLE && - event->xbutton.button == 1 && - meta_display_is_double_click (frame->window->display)) - { - meta_verbose ("Double click on title\n"); - - /* FIXME this catches double click that starts elsewhere - * with the second click on title, maybe no one will - * ever notice - */ - - if (frame->window->shaded) - meta_window_unshade (frame->window); - else - meta_window_shade (frame->window); - } - else if (((control == META_FRAME_CONTROL_TITLE || - control == META_FRAME_CONTROL_NONE) && - event->xbutton.button == 1) || - event->xbutton.button == 2) - { - meta_verbose ("Begin move on %s\n", - frame->window->desc); - grab_action (frame, META_FRAME_ACTION_MOVING, - event->xbutton.time); - frame->grab->start_root_x = event->xbutton.x_root; - frame->grab->start_root_y = event->xbutton.y_root; - /* pos of client in root coords */ - frame->grab->start_window_x = - frame->rect.x + frame->window->rect.x; - frame->grab->start_window_y = - frame->rect.y + frame->window->rect.y; - frame->grab->start_button = event->xbutton.button; - } - else if (control == META_FRAME_CONTROL_DELETE && - event->xbutton.button == 1) - { - meta_verbose ("Close control clicked on %s\n", - frame->window->desc); - grab_action (frame, META_FRAME_ACTION_DELETING, - event->xbutton.time); - frame->grab->start_button = event->xbutton.button; - } - else if (control == META_FRAME_CONTROL_MAXIMIZE && - event->xbutton.button == 1) - { - meta_verbose ("Maximize control clicked on %s\n", - frame->window->desc); - grab_action (frame, META_FRAME_ACTION_TOGGLING_MAXIMIZE, - event->xbutton.time); - frame->grab->start_button = event->xbutton.button; - } - else if (control == META_FRAME_CONTROL_RESIZE_SE && - event->xbutton.button == 1) - { - meta_verbose ("Resize control clicked on %s\n", - frame->window->desc); - grab_action (frame, META_FRAME_ACTION_RESIZING_SE, - event->xbutton.time); - frame->grab->start_root_x = event->xbutton.x_root; - frame->grab->start_root_y = event->xbutton.y_root; - frame->grab->start_window_x = frame->window->rect.width; - frame->grab->start_window_y = frame->window->rect.height; - frame->grab->start_button = event->xbutton.button; - } - else if (control == META_FRAME_CONTROL_MENU && - event->xbutton.button == 1) - { - int x, y, width, height; - MetaFrameInfo info; - MetaMessageWindowMenuOps ops; - MetaMessageWindowMenuOps insensitive; - - meta_verbose ("Menu control clicked on %s\n", - frame->window->desc); - - meta_frame_init_info (frame, &info); - frame->window->screen->engine->get_control_rect (&info, - META_FRAME_CONTROL_MENU, - &x, &y, &width, &height, - frame->theme_data); - - /* Let the menu get a grab. The user could release button - * before the menu gets the grab, in which case the - * menu gets somewhat confused, but it's not that - * disastrous. - */ - XUngrabPointer (frame->window->display->xdisplay, - event->xbutton.time); - - get_menu_items (frame, &info, &ops, &insensitive); - - meta_ui_slave_show_window_menu (frame->window->screen->uislave, - frame->window, - frame->rect.x + x, - frame->rect.y + y + height, - event->xbutton.button, - ops, insensitive, - event->xbutton.time); - } - } - break; - case ButtonRelease: - if (frame->grab) - meta_debug_spew ("Here! grab %p action %d buttons %d %d\n", - frame->grab, frame->grab->action, frame->grab->start_button, event->xbutton.button); - if (frame->grab && - event->xbutton.button == frame->grab->start_button) - { - switch (frame->grab->action) - { - case META_FRAME_ACTION_MOVING: - update_move (frame, event->xbutton.x_root, event->xbutton.y_root); - ungrab_action (frame, event->xbutton.time); - update_current_control (frame, - event->xbutton.x_root, event->xbutton.y_root); - break; - - case META_FRAME_ACTION_RESIZING_SE: - update_resize_se (frame, event->xbutton.x_root, event->xbutton.y_root); - ungrab_action (frame, event->xbutton.time); - update_current_control (frame, - event->xbutton.x_root, event->xbutton.y_root); - break; - - case META_FRAME_ACTION_DELETING: - /* Must ungrab before getting "real" control position */ - ungrab_action (frame, event->xbutton.time); - update_current_control (frame, - event->xbutton.x_root, - event->xbutton.y_root); - /* delete if we're still over the button */ - if (frame->current_control == META_FRAME_CONTROL_DELETE) - meta_window_delete (frame->window, event->xbutton.time); - break; - case META_FRAME_ACTION_TOGGLING_MAXIMIZE: - /* Must ungrab before getting "real" control position */ - ungrab_action (frame, event->xbutton.time); - update_current_control (frame, - event->xbutton.x_root, - event->xbutton.y_root); - /* delete if we're still over the button */ - if (frame->current_control == META_FRAME_CONTROL_MAXIMIZE) - { - if (frame->window->maximized) - meta_window_unmaximize (frame->window); - else - meta_window_maximize (frame->window); - } - break; - default: - meta_warning ("Unhandled action in button release\n"); - break; - } - } - break; - case MotionNotify: - { - int x, y; - - frame_query_root_pointer (frame, &x, &y); - if (frame->grab) - { - switch (frame->grab->action) - { - case META_FRAME_ACTION_MOVING: - update_move (frame, x, y); - break; - - case META_FRAME_ACTION_RESIZING_SE: - update_resize_se (frame, x, y); - break; - - case META_FRAME_ACTION_NONE: - - break; - default: - break; - } - } - else - { - update_current_control (frame, x, y); - } - } - break; - case EnterNotify: - /* We handle it here if a decorated window - * is involved, otherwise we handle it in display.c - */ - /* do this even if window->has_focus to avoid races */ - meta_window_focus (frame->window, - event->xcrossing.time); - break; - case LeaveNotify: - update_current_control (frame, -1, -1); - break; - case FocusIn: - break; - case FocusOut: - break; - case KeymapNotify: - break; - case Expose: - { - gboolean title_was_exposed = frame->title_exposed; - meta_frame_queue_draw (frame); - if (!title_was_exposed && - event->xexpose.y > frame->child_y) - frame->title_exposed = FALSE; - } - break; - case GraphicsExpose: - break; - case NoExpose: - break; - case VisibilityNotify: - break; - case CreateNotify: - break; - case DestroyNotify: - { - MetaDisplay *display; - - meta_warning ("Unexpected destruction of frame 0x%lx, not sure if this should silently fail or be considered a bug\n", frame->xwindow); - display = frame->window->display; - meta_error_trap_push (display); - meta_window_destroy_frame (frame->window); - meta_error_trap_pop (display); - return TRUE; - } - break; - case UnmapNotify: - if (frame->grab) - ungrab_action (frame, CurrentTime); - break; - case MapNotify: - if (frame->grab) - ungrab_action (frame, CurrentTime); - break; - case MapRequest: - break; - case ReparentNotify: - break; - case ConfigureNotify: - break; - case ConfigureRequest: - { - /* This is a request from the UISlave, or else a client - * that's completely out of line. We call - * meta_window_move_resize() using this information. - */ - - } - break; - case GravityNotify: - break; - case ResizeRequest: - break; - case CirculateNotify: - break; - case CirculateRequest: - break; - case PropertyNotify: - break; - case SelectionClear: - break; - case SelectionRequest: - break; - case SelectionNotify: - break; - case ColormapNotify: - break; - case ClientMessage: - break; - case MappingNotify: - break; - default: - break; - } - - return FALSE; -} -#endif diff --git a/src/frames.h b/src/frames.h index fe6bcc4af..dc7034523 100644 --- a/src/frames.h +++ b/src/frames.h @@ -52,7 +52,14 @@ typedef enum META_FRAME_STATUS_CLICKING_MAXIMIZE, META_FRAME_STATUS_CLICKING_DELETE, META_FRAME_STATUS_CLICKING_MENU, - META_FRAME_STATUS_RESIZING_SE + 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 @@ -89,14 +96,19 @@ struct _MetaFrames int text_height; GHashTable *frames; + + guint tooltip_timeout; + MetaUIFrame *last_motion_frame; /* 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 */ + /* 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; }; diff --git a/src/run-metacity.sh b/src/run-metacity.sh index 4f527ca6f..e50768935 100755 --- a/src/run-metacity.sh +++ b/src/run-metacity.sh @@ -1,6 +1,6 @@ #! /bin/bash if test -z "$SCREENS"; then - SCREENS=2 + SCREENS=1 fi if test "$DEBUG" = none; then diff --git a/src/uislave/Makefile.am b/src/uislave/Makefile.am deleted file mode 100644 index 1f93d1aab..000000000 --- a/src/uislave/Makefile.am +++ /dev/null @@ -1,17 +0,0 @@ - -INCLUDES=@UISLAVE_CFLAGS@ -DHOST_ALIAS=\"@HOST_ALIAS@\" - -metacity_uislave_SOURCES = \ - fixedtip.h \ - fixedtip.c \ - main.c \ - menu.c \ - menu.h \ - messages.c \ - messages.h \ - messagequeue.c \ - messagequeue.h - -libexec_PROGRAMS=metacity-uislave - -metacity_uislave_LDADD = @UISLAVE_LIBS@ \ No newline at end of file diff --git a/src/uislave/fixedtip.c b/src/uislave/fixedtip.c deleted file mode 100644 index bb12e405b..000000000 --- a/src/uislave/fixedtip.c +++ /dev/null @@ -1,78 +0,0 @@ -/* Metacity fixed tooltip routine */ - -/* - * Copyright (C) 2001 Havoc Pennington - * - * 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. - */ - -#include "fixedtip.h" - -static GtkWidget *tip = NULL; -static GtkWidget *label = NULL; - -static gint -expose_handler (GtkTooltips *tooltips) -{ - gtk_paint_flat_box (tip->style, tip->window, - GTK_STATE_NORMAL, GTK_SHADOW_OUT, - NULL, tip, "tooltip", - 0, 0, -1, -1); - - return FALSE; -} - -void -meta_fixed_tip_show (int root_x, int root_y, - const char *markup_text) -{ - if (tip == NULL) - { - tip = gtk_window_new (GTK_WINDOW_POPUP); - gtk_widget_set_app_paintable (tip, TRUE); - gtk_window_set_policy (GTK_WINDOW (tip), FALSE, FALSE, TRUE); - gtk_widget_set_name (tip, "gtk-tooltips"); - gtk_container_set_border_width (GTK_CONTAINER (tip), 4); - - gtk_signal_connect_object (GTK_OBJECT (tip), - "expose_event", - GTK_SIGNAL_FUNC (expose_handler), - NULL); - - label = gtk_label_new (NULL); - gtk_label_set_line_wrap (GTK_LABEL (label), TRUE); - gtk_misc_set_alignment (GTK_MISC (label), 0.5, 0.5); - gtk_widget_show (label); - - gtk_container_add (GTK_CONTAINER (tip), label); - - gtk_signal_connect (GTK_OBJECT (tip), - "destroy", - GTK_SIGNAL_FUNC (gtk_widget_destroyed), - &tip); - } - - gtk_widget_set_uposition (tip, root_x, root_y); - gtk_label_set_markup (GTK_LABEL (label), markup_text); - - gtk_widget_show (tip); -} - -void -meta_fixed_tip_hide (void) -{ - gtk_widget_destroy (tip); -} diff --git a/src/uislave/fixedtip.h b/src/uislave/fixedtip.h deleted file mode 100644 index 4b637fc6e..000000000 --- a/src/uislave/fixedtip.h +++ /dev/null @@ -1,32 +0,0 @@ -/* Metacity fixed tooltip routine */ - -/* - * Copyright (C) 2001 Havoc Pennington - * - * 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. - */ - -#ifndef META_FIXED_TIP_H -#define META_FIXED_TIP_H - -#include - -void meta_fixed_tip_show (int root_x, int root_y, - const char *markup_text); -void meta_fixed_tip_hide (void); - - -#endif diff --git a/src/uislave/frames.c b/src/uislave/frames.c deleted file mode 100644 index cb7e9d8b0..000000000 --- a/src/uislave/frames.c +++ /dev/null @@ -1,928 +0,0 @@ -/* Metacity window frame manager widget */ - -/* - * Copyright (C) 2001 Havoc Pennington - * - * 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. - */ - -#include "frames.h" - -struct _MetaFrame -{ - Window xwindow; - GdkWindow *window; - PangoLayout *layout; - MetaFrameFlags flags; - /* w/h of frame window */ - int width; - int height; -}; - -struct _MetaFrameProperties -{ - /* Size of left/right/bottom sides */ - int left_width; - int right_width; - int bottom_height; - - /* Border of blue title region */ - GtkBorder title_border; - - /* Border inside title region, around title */ - GtkBorder text_border; - - /* padding on either side of spacer */ - int spacer_padding; - - /* Size of spacer */ - int spacer_width; - int spacer_height; - - /* indent of buttons from edges of frame */ - int right_inset; - int left_inset; - - /* Size of buttons */ - int button_width; - int button_height; - - /* Space around buttons */ - GtkBorder button_border; - - /* Space inside button which is clickable but doesn't draw the - * button icon - */ - GtkBorder inner_button_border; -}; - -typedef struct _MetaFrameGeometry MetaFrameGeometry; - -struct _MetaFrameGeometry -{ - int left_width; - int right_width; - int top_height; - int bottom_height; - - MetaRectangle close_rect; - MetaRectangle max_rect; - MetaRectangle min_rect; - MetaRectangle spacer_rect; - MetaRectangle menu_rect; - MetaRectangle title_rect; -}; - -static void meta_frames_class_init (MetaFramesClass *klass); -static void meta_frames_init (MetaFrames *frames); -static void meta_frames_destroy (GtkObject *object); -static void meta_frames_finalize (GObject *object); -static void meta_frames_style_set (GtkWidget *widget, - GtkStyle *prev_style); - -gboolean meta_frames_button_press_event (GtkWidget *widget, - GdkEventButton *event); -gboolean meta_frames_button_release_event (GtkWidget *widget, - GdkEventButton *event); -gboolean meta_frames_motion_notify_event (GtkWidget *widget, - GdkEventMotion *event); -gboolean meta_frames_destroy_event (GtkWidget *widget, - GdkEventAny *event); -gboolean meta_frames_expose_event (GtkWidget *widget, - GdkEventExpose *event); -gboolean meta_frames_key_press_event (GtkWidget *widget, - GdkEventKey *event); -gboolean meta_frames_key_release_event (GtkWidget *widget, - GdkEventKey *event); -gboolean meta_frames_enter_notify_event (GtkWidget *widget, - GdkEventCrossing *event); -gboolean meta_frames_leave_notify_event (GtkWidget *widget, - GdkEventCrossing *event); -gboolean meta_frames_configure_event (GtkWidget *widget, - GdkEventConfigure *event); -gboolean meta_frames_focus_in_event (GtkWidget *widget, - GdkEventFocus *event); -gboolean meta_frames_focus_out_event (GtkWidget *widget, - GdkEventFocus *event); -gboolean meta_frames_map_event (GtkWidget *widget, - GdkEventAny *event); -gboolean meta_frames_unmap_event (GtkWidget *widget, - GdkEventAny *event); -gboolean meta_frames_property_notify_event (GtkWidget *widget, - GdkEventProperty *event); -gboolean meta_frames_client_event (GtkWidget *widget, - GdkEventClient *event); -gboolean meta_frames_window_state_event (GtkWidget *widget, - GdkEventWindowState *event); - - -static void meta_frames_calc_geometry (MetaFrames *frames, - MetaFrameGeometry *fgeom); - -static MetaFrame* meta_frames_lookup_window (MetaFrames *frames, - Window xwindow); - -static GtkWidgetClass *parent_class = NULL; -static guint signals[LAST_SIGNAL]; - -GtkType -meta_frames_get_type (void) -{ - static GtkType frames_type = 0; - - if (!frames_type) - { - static const GtkTypeInfo frames_info = - { - "MetaFrames", - sizeof (MetaFrames), - sizeof (MetaFramesClass), - (GtkClassInitFunc) meta_frames_class_init, - (GtkObjectInitFunc) meta_frames_init, - /* reserved_1 */ NULL, - /* reserved_2 */ NULL, - (GtkClassInitFunc) NULL, - }; - - frames_type = gtk_type_unique (GTK_TYPE_WIDGET, &frames_info); - } - - return frames_type; -} - -#define BORDER_PROPERTY (name, blurb, docs) \ - gtk_widget_class_install_style_property (widget_class, \ - g_param_spec_boxed (name, \ - blurb, \ - docs, \ - GTK_TYPE_BORDER, \ - G_PARAM_READABLE)) - -#define INT_PROPERTY (name, default, blurb, docs) \ - gtk_widget_class_install_style_property (widget_class, \ - g_param_spec_int (name, \ - blurb, \ - docs, \ - 0, \ - G_MAXINT, \ - default, \ - G_PARAM_READABLE)) - -static void -meta_frames_class_init (MetaFramesClass *class) -{ - GObjectClass *gobject_class; - GtkObjectClass *object_class; - GtkWidgetClass *widget_class; - - gobject_class = G_OBJECT_CLASS (class); - object_class = (GtkObjectClass*) class; - widget_class = (GtkWidgetClass*) class; - - parent_class = g_type_class_peek_parent (class); - - gobject_class->finalize = meta_frames_finalize; - object_class->destroy = meta_frames_destroy; - - widget_class->style_set = meta_frames_style_set; - - INT_PROPERTY ("left_width", 6, _("Left edge"), _("Left window edge width")); - INT_PROPERTY ("right_width", 6, _("Right edge"), _("Right window edge width")); - INT_PROPERTY ("bottom_height", 7, _("Bottom edge"), _("Bottom window edge height")); - - BORDER_PROPERTY ("title_border", _("Title border"), _("Border around title area")); - BORDER_PROPERTY ("text_border", _("Text border"), _("Border around window title text")); - - INT_PROPERTY ("spacer_padding", 3, _("Spacer padding"), _("Padding on either side of spacer")); - INT_PROPERTY ("spacer_width", 2, _("Spacer width"), _("Width of spacer")); - INT_PROPERTY ("spacer_height", 10, _("Spacer height"), _("Height of spacer")); - - /* same as right_width left_width by default */ - INT_PROPERTY ("right_inset", 6, _("Right inset"), _("Distance of buttons from right edge of frame")); - INT_PROPERTY ("left_inset", 6, _("Left inset"), _("Distance of menu button from left edge of frame")); - - INT_PROPERTY ("button_width", 14, _("Button width"), _("Width of buttons")); - INT_PROPERTY ("button_height", 14, _("Button height"), _("Height of buttons")); - - BORDER_PROPERTY ("button_border", _("Button border"), _("Border around buttons")); - BORDER_PROPERTY ("inner_button_border", _("Inner button border"), _("Border around the icon inside buttons")); -} - -static gint -unsigned_long_equal (gconstpointer v1, - gconstpointer v2) -{ - return *((const gulong*) v1) == *((const gulong*) v2); -} - -static guint -unsigned_long_hash (gconstpointer v) -{ - gulong val = * (const gulong *) v; - - /* I'm not sure this works so well. */ -#if G_SIZEOF_LONG > 4 - return (guint) (val ^ (val >> 32)); -#else - return val; -#endif -} - -static void -meta_frames_init (MetaFrames *frames) -{ - GTK_WINDOW (frames)->type = GTK_WINDOW_POPUP; - - frames->props = g_new0 (MetaFrameProperties, 1); - - frames->frames = g_hash_table_new (unsigned_long_hash, unsigned_long_equal); -} - -static void -meta_frames_destroy (GtkObject *object) -{ - - GTK_OBJECT_CLASS (parent_class)->destroy (object); -} - -static void -listify_func (gpointer key, gpointer value, gpointer data) -{ - GSList **listp; - - listp = data; - *listp = g_slist_prepend (*listp, value); -} - -static void -meta_frames_finalize (GObject *object) -{ - MetaFrames *frames; - GSList *winlist; - GSList *tmp; - - frames = META_FRAMES (object); - - winlist = NULL; - g_hash_table_foreach (frames->frames, - listify_func, - &winlist); - - /* Unmanage all frames */ - tmp = winlist; - while (tmp != NULL) - { - MetaFrame *frame; - - frame = tmp->data; - - meta_frames_unmanage_window (frames, frame->xwindow); - - tmp = tmp->next; - } - g_slist_free (winlist); - - g_assert (g_hash_table_size (frames->frames) == 0); - g_hash_table_destroy (frames->frames); - - g_free (frames->props); - - G_OBJECT_CLASS (parent_class)->finalize (object); -} - -static void -meta_frames_style_set (GtkWidget *widget, - GtkStyle *prev_style) -{ - MetaFrames *frames; - /* left, right, top, bottom */ - static GtkBorder default_title_border = { 3, 4, 4, 3 }; - static GtkBorder default_text_border = { 2, 2, 2, 2 }; - static GtkBorder default_button_border = { 1, 1, 1, 1 }; - static GtkBorder default_inner_button_border = { 3, 3, 3, 3 }; - GtkBorder *title_border; - GtkBorder *text_border; - GtkBorder *button_border; - GtkBorder *inner_button_border; - MetaFrameProperties props; - - frames = META_FRAMES (widget); - - gtk_widget_style_get (widget, - "left_width", - &props.left_width, - "right_width", - &props.right_width, - "bottom_height", - &props.bottom_height, - "title_border", - &title_border, - "text_border", - &text_border, - "spacer_padding", - &props.spacer_padding, - "spacer_width", - &props.spacer_width, - "spacer_height", - &props.spacer_height, - "right_inset", - &props.right_inset, - "left_inset", - &props.left_inset, - "button_width", - &props.button_width, - "button_height", - &props.button_height, - "button_border", - &button_border, - "inner_button_border", - &inner_button_border, - NULL); - - if (title_border) - props.title_border = *title_border; - else - props.title_border = default_title_border; - - g_free (title_border); - - if (text_border) - props.text_border = *text_border; - else - props.text_border = default_text_border; - - g_free (text_border); - - if (button_border) - props.button_border = *button_border; - else - props.button_border = default_button_border; - - g_free (button_border); - - if (inner_button_border) - props.inner_button_border = *inner_button_border; - else - props.inner_button_border = default_inner_button_border; - - g_free (inner_button_border); - - *(frames->props) = props; - - { - PangoFontMetrics metrics; - PangoFont *font; - gchar *lang; - - font = pango_context_load_font (gtk_widget_get_pango_context (widget), - widget->style->font_desc); - lang = pango_context_get_lang (gtk_widget_get_pango_context (widget)); - pango_font_get_metrics (font, lang, &metrics); - g_free (lang); - - g_object_unref (G_OBJECT (font)); - - frames->text_height = metrics.ascent + metrics.descent; - } -} - -static void -meta_frames_calc_geometry (MetaFrames *frames, - MetaFrame *frame, - MetaFrameGeometry *fgeom) -{ - int x; - int button_y; - int title_right_edge; - gboolean shaded; - MetaFrameProperties props; - int buttons_height, title_height, spacer_height; - - props = *(frames->props); - - buttons_height = props.button_height + - props.button_border.top + props.button_border.bottom; - title_height = frames->text_height + - props.text_border.top + props.text_border.bottom + - props.title_border.top + props.title_border.bottom; - spacer_height = props.spacer_height; - - fgeom->top_height = MAX (buttons_height, title_height); - fgeom->top_height = MAX (fgeom->top_height, spacer_height); - - fgeom->left_width = props.left_width; - fgeom->right_width = props.right_width; - - if (frame->flags & META_FRAME_SHADED) - fgeom->bottom_height = 0; - else - fgeom->bottom_height = props.bottom_height; - - x = frame->width - fgeom->button_inset; - - /* center buttons */ - button_y = (fgeom->top_height - - (props.button_height + props.button_border.top + props.button_border.bottom)) / 2 + props.button_border.top; - - if ((frame->flags & META_FRAME_ALLOWS_DELETE) && - x >= 0) - { - fgeom->close_rect.x = x - props.button_border.right - props.button_width; - fgeom->close_rect.y = button_y; - fgeom->close_rect.width = props.button_width; - fgeom->close_rect.height = props.button_height; - - x = fgeom->close_rect.x - props.button_border.left; - } - else - { - fgeom->close_rect.x = 0; - fgeom->close_rect.y = 0; - fgeom->close_rect.width = 0; - fgeom->close_rect.height = 0; - } - - if ((frame->flags & META_FRAME_ALLOWS_MAXIMIZE) && - x >= 0) - { - fgeom->max_rect.x = x - props.button_border.right - props.button_width; - fgeom->max_rect.y = button_y; - fgeom->max_rect.width = props.button_width; - fgeom->max_rect.height = props.button_height; - - x = fgeom->max_rect.x - props.button_border.left; - } - else - { - fgeom->max_rect.x = 0; - fgeom->max_rect.y = 0; - fgeom->max_rect.width = 0; - fgeom->max_rect.height = 0; - } - - if ((frame->flags & META_FRAME_ALLOWS_MINIMIZE) && - x >= 0) - { - fgeom->min_rect.x = x - props.button_border.right - props.button_width; - fgeom->min_rect.y = button_y; - fgeom->min_rect.width = props.button_width; - fgeom->min_rect.height = props.button_height; - - x = fgeom->min_rect.x - props.button_border.left; - } - else - { - fgeom->min_rect.x = 0; - fgeom->min_rect.y = 0; - fgeom->min_rect.width = 0; - fgeom->min_rect.height = 0; - } - - if ((fgeom->close_rect.width > 0 || - fgeom->max_rect.width > 0 || - fgeom->min_rect.width > 0) && - x >= 0) - { - fgeom->spacer_rect.x = x - props.spacer_padding - props.spacer_width; - fgeom->spacer_rect.y = (fgeom->top_height - props.spacer_height) / 2; - fgeom->spacer_rect.width = props.spacer_width; - fgeom->spacer_rect.height = props.spacer_height; - - x = fgeom->spacer_rect.x - props.spacer_padding; - } - else - { - fgeom->spacer_rect.x = 0; - fgeom->spacer_rect.y = 0; - fgeom->spacer_rect.width = 0; - fgeom->spacer_rect.height = 0; - } - - title_right_edge = x - props.title_border.right; - - /* Now x changes to be position from the left */ - x = fgeom->left_inset; - - if ((frame->flags & META_FRAME_ALLOWS_MENU) && - x < title_right_edge) - { - fgeom->menu_rect.x = x + props.button_border.left; - fgeom->menu_rect.y = button_y; - fgeom->menu_rect.width = props.button_width; - fgeom->menu_rect.height = props.button_height; - - x = fgeom->menu_rect.x + fgeom->menu_rect.width + props.button_border.right; - } - else - { - fgeom->menu_rect.x = 0; - fgeom->menu_rect.y = 0; - fgeom->menu_rect.width = 0; - fgeom->menu_rect.height = 0; - } - - /* If menu overlaps close button, then the menu wins since it - * lets you perform any operation including close - */ - if (fgeom->close_rect.width > 0 && - fgeom->close_rect.x < (fgeom->menu_rect.x + fgeom->menu_rect.height)) - { - fgeom->close_rect.width = 0; - fgeom->close_rect.height = 0; - } - - /* We always fill as much vertical space as possible with title rect, - * rather than centering it like the buttons and spacer - */ - fgeom->title_rect.x = x + props.title_border.left; - fgeom->title_rect.y = props.title_border.top; - fgeom->title_rect.width = title_right_edge - fgeom->title_rect.x; - fgeom->title_rect.height = frames->top_height - props.title_border.top - props.title_border.bottom; - - /* Nuke title if it won't fit */ - if (fgeom->title_rect.width < 0 || - fgeom->title_rect.height < 0) - { - fgeom->title_rect.width = 0; - fgeom->title_rect.height = 0; - } -} - -void -meta_frames_manage_window (MetaFrames *frames, - Window xwindow) -{ - MetaFrame *frame; - - g_return_if_fail (GDK_IS_WINDOW (window)); - - frame = g_new (MetaFrame, 1); - - gdk_error_trap_push (); - - frame->window = gdk_window_foreign_new (xwindow); - - if (frame->window == NULL) - { - gdk_flush (); - gdk_error_trap_pop (); - g_free (frame); - meta_ui_warning ("Frame 0x%lx disappeared as we managed it\n", xwindow); - return; - } - - gdk_window_set_user_data (frame->window, frames); - - gdk_window_set_events (frame->window, - GDK_EXPOSURE_MASK | - GDK_POINTER_MOTION_MASK | - GDK_POINTER_MOTION_HINT_MASK | - GDK_BUTTON_PRESS_MASK | - GDK_BUTTON_RELEASE_MASK | - GDK_STRUCTURE_MASK); - - gdk_drawable_get_size (GDK_DRAWABLE (frame->window), - &frame->width, &frame->height); - - XGrabButton (gdk_display, AnyButton, AnyModifier, - xwindow, False, - ButtonPressMask | ButtonReleaseMask | - PointerMotionMask | PointerMotionHintMask, - GrabModeAsync, GrabModeAsync, - False, None); - - gdk_flush (); - if (gdk_error_trap_pop ()) - { - g_object_unref (G_OBJECT (frame->window)); - g_free (frame); - meta_ui_warning ("Errors managing frame 0x%lx\n", xwindow); - return; - } - - frame->xwindow = xwindow; - frame->layout = NULL; - frame->flags = 0; - - g_hash_table_insert (frames->frames, &frame->xwindow); -} - -void -meta_frames_unmanage_window (MetaFrames *frames, - Window xwindow) -{ - MetaFrame *frame; - - frame = g_hash_table_lookup (frames->frames, &xwindow); - - if (frame) - { - g_hash_table_remove (frames->frames, &frame->xwindow); - - g_object_unref (G_OBJECT (frame->window)); - - if (frame->layout) - g_object_unref (G_OBJECT (frame->layout)); - - g_free (frame); - } - else - meta_ui_warning ("Frame 0x%lx not managed, can't unmanage\n", xwindow); -} - -static MetaFrame* -meta_frames_lookup_window (MetaFrames *frames, - Window xwindow) -{ - MetaFrame *frame; - - frame = g_hash_table_lookup (frames->frames, &xwindow); - - return frame; -} - -gboolean -meta_frames_button_press_event (GtkWidget *widget, - GdkEventButton *event) -{ - MetaFrame *frame; - MetaFrames *frames; - - frames = META_FRAMES (widget); - - frame = meta_frames_lookup_window (frames, GDK_WINDOW_XID (event->window)); - if (frame == NULL) - return FALSE; - - return TRUE; -} - -gboolean -meta_frames_button_release_event (GtkWidget *widget, - GdkEventButton *event) -{ - MetaFrame *frame; - MetaFrames *frames; - - frames = META_FRAMES (widget); - - frame = meta_frames_lookup_window (frames, GDK_WINDOW_XID (event->window)); - if (frame == NULL) - return FALSE; - - return TRUE; -} - -gboolean -meta_frames_motion_notify_event (GtkWidget *widget, - GdkEventMotion *event) -{ - MetaFrame *frame; - MetaFrames *frames; - - frames = META_FRAMES (widget); - - frame = meta_frames_lookup_window (frames, GDK_WINDOW_XID (event->window)); - if (frame == NULL) - return FALSE; - - return TRUE; -} - -gboolean -meta_frames_destroy_event (GtkWidget *widget, - GdkEventAny *event) -{ - MetaFrame *frame; - MetaFrames *frames; - - frames = META_FRAMES (widget); - - frame = meta_frames_lookup_window (frames, GDK_WINDOW_XID (event->window)); - if (frame == NULL) - return FALSE; - - return TRUE; -} - -gboolean -meta_frames_expose_event (GtkWidget *widget, - GdkEventExpose *event) -{ - MetaFrame *frame; - MetaFrames *frames; - - frames = META_FRAMES (widget); - - frame = meta_frames_lookup_window (frames, GDK_WINDOW_XID (event->window)); - if (frame == NULL) - return FALSE; - - return TRUE; -} - -gboolean -meta_frames_key_press_event (GtkWidget *widget, - GdkEventKey *event) -{ - MetaFrame *frame; - MetaFrames *frames; - - frames = META_FRAMES (widget); - - frame = meta_frames_lookup_window (frames, GDK_WINDOW_XID (event->window)); - if (frame == NULL) - return FALSE; - - return TRUE; -} - -gboolean -meta_frames_key_release_event (GtkWidget *widget, - GdkEventKey *event) -{ - MetaFrame *frame; - MetaFrames *frames; - - frames = META_FRAMES (widget); - - frame = meta_frames_lookup_window (frames, GDK_WINDOW_XID (event->window)); - if (frame == NULL) - return FALSE; - - return TRUE; -} - -gboolean -meta_frames_enter_notify_event (GtkWidget *widget, - GdkEventCrossing *event) -{ - MetaFrame *frame; - MetaFrames *frames; - - frames = META_FRAMES (widget); - - frame = meta_frames_lookup_window (frames, GDK_WINDOW_XID (event->window)); - if (frame == NULL) - return FALSE; - - return TRUE; -} - -gboolean -meta_frames_leave_notify_event (GtkWidget *widget, - GdkEventCrossing *event) -{ - MetaFrame *frame; - MetaFrames *frames; - - frames = META_FRAMES (widget); - - frame = meta_frames_lookup_window (frames, GDK_WINDOW_XID (event->window)); - if (frame == NULL) - return FALSE; - - return TRUE; -} - -gboolean -meta_frames_configure_event (GtkWidget *widget, - GdkEventConfigure *event) -{ - MetaFrame *frame; - MetaFrames *frames; - - frames = META_FRAMES (widget); - - frame = meta_frames_lookup_window (frames, GDK_WINDOW_XID (event->window)); - if (frame == NULL) - return FALSE; - - return TRUE; -} - -gboolean -meta_frames_focus_in_event (GtkWidget *widget, - GdkEventFocus *event) -{ - MetaFrame *frame; - MetaFrames *frames; - - frames = META_FRAMES (widget); - - frame = meta_frames_lookup_window (frames, GDK_WINDOW_XID (event->window)); - if (frame == NULL) - return FALSE; - - return TRUE; -} - -gboolean -meta_frames_focus_out_event (GtkWidget *widget, - GdkEventFocus *event) -{ - MetaFrame *frame; - MetaFrames *frames; - - frames = META_FRAMES (widget); - - frame = meta_frames_lookup_window (frames, GDK_WINDOW_XID (event->window)); - if (frame == NULL) - return FALSE; - - return TRUE; -} - -gboolean -meta_frames_map_event (GtkWidget *widget, - GdkEventAny *event) -{ - MetaFrame *frame; - MetaFrames *frames; - - frames = META_FRAMES (widget); - - frame = meta_frames_lookup_window (frames, GDK_WINDOW_XID (event->window)); - if (frame == NULL) - return FALSE; - - return TRUE; -} - -gboolean -meta_frames_unmap_event (GtkWidget *widget, - GdkEventAny *event) -{ - MetaFrame *frame; - MetaFrames *frames; - - frames = META_FRAMES (widget); - - frame = meta_frames_lookup_window (frames, GDK_WINDOW_XID (event->window)); - if (frame == NULL) - return FALSE; - - return TRUE; -} - -gboolean -meta_frames_property_notify_event (GtkWidget *widget, - GdkEventProperty *event) -{ - MetaFrame *frame; - MetaFrames *frames; - - frames = META_FRAMES (widget); - - frame = meta_frames_lookup_window (frames, GDK_WINDOW_XID (event->window)); - if (frame == NULL) - return FALSE; - - return TRUE; -} - -gboolean -meta_frames_client_event (GtkWidget *widget, - GdkEventClient *event) -{ - MetaFrame *frame; - MetaFrames *frames; - - frames = META_FRAMES (widget); - - frame = meta_frames_lookup_window (frames, GDK_WINDOW_XID (event->window)); - if (frame == NULL) - return FALSE; - - return TRUE; -} - -gboolean -meta_frames_window_state_event (GtkWidget *widget, - GdkEventWindowState *event) -{ - MetaFrame *frame; - MetaFrames *frames; - - frames = META_FRAMES (widget); - - frame = meta_frames_lookup_window (frames, GDK_WINDOW_XID (event->window)); - if (frame == NULL) - return FALSE; - - return TRUE; -} - diff --git a/src/uislave/frames.h b/src/uislave/frames.h deleted file mode 100644 index 5a263c547..000000000 --- a/src/uislave/frames.h +++ /dev/null @@ -1,77 +0,0 @@ -/* Metacity window frame manager widget */ - -/* - * Copyright (C) 2001 Havoc Pennington - * - * 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. - */ - -#ifndef META_FRAMES_H -#define META_FRAMES_H - -#include -#include -#include "messages.h" - -/* This is one widget that manages all the window frames - * as subwindows. - */ - -#define META_TYPE_FRAMES (meta_frames_get_type ()) -#define META_FRAMES(obj) (META_CHECK_CAST ((obj), META_TYPE_FRAMES, MetaFrames)) -#define META_FRAMES_CLASS(klass) (META_CHECK_CLASS_CAST ((klass), META_TYPE_FRAMES, MetaFramesClass)) -#define META_IS_FRAMES(obj) (META_CHECK_TYPE ((obj), META_TYPE_FRAMES)) -#define META_IS_FRAMES_CLASS(klass) (META_CHECK_CLASS_TYPE ((klass), META_TYPE_FRAMES)) -#define META_FRAMES_GET_CLASS(obj) (META_CHECK_GET_CLASS ((obj), META_TYPE_FRAMES, MetaFramesClass)) - -typedef struct _MetaFrames MetaFrames; -typedef struct _MetaFramesClass MetaFramesClass; - -typedef struct _MetaFrame MetaFrame; -typedef struct _MetaFrameProperties MetaFrameProperties; - -struct _MetaFrames -{ - GtkWindow parent_instance; - - /* If we did a widget per frame, we wouldn't want to cache this. */ - MetaFrameProperties *props; - - int text_height; - - GHashTable *frames; -}; - -struct _MetaFramesClass -{ - GtkWindowClass parent_class; - -}; - -GType meta_frames_get_type (void) G_GNUC_CONST; - -MetaFrames *meta_frames_new (void); - -void meta_frames_manage_window (MetaFrames *frames, - Window xwindow); -void meta_frames_unmanage_window (MetaFrames *frames, - Window xwindow); - -void meta_frames_set_title (MetaFrames *frames, - Window xwindow, - const char *title); - -#endif diff --git a/src/uislave/main.c b/src/uislave/main.c deleted file mode 100644 index f419f3402..000000000 --- a/src/uislave/main.c +++ /dev/null @@ -1,142 +0,0 @@ -/* Metacity UI slave main() */ - -/* - * Copyright (C) 2001 Havoc Pennington - * - * 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. - */ - -#include "messages.h" -#include "messagequeue.h" -#include "fixedtip.h" -#include "main.h" -#include "menu.h" - -#include -#include -#include - -#include - -static void message_callback (MetaMessageQueue *mq, - MetaMessage *message, - gpointer data); - -int -main (int argc, char **argv) -{ - MetaMessageQueue *mq; - - /* report our nature to the window manager */ - meta_message_send_check (); - - gtk_init (&argc, &argv); - - mq = meta_message_queue_new (0, message_callback, NULL); - - gtk_main (); - - return 0; -} - -static void -message_callback (MetaMessageQueue *mq, - MetaMessage *message, - gpointer data) -{ - switch (message->header.message_code) - { - case MetaMessageShowTipCode: - meta_fixed_tip_show (message->show_tip.root_x, - message->show_tip.root_y, - message->show_tip.markup); - break; - - case MetaMessageHideTipCode: - meta_fixed_tip_hide (); - break; - - case MetaMessageShowWindowMenuCode: - meta_window_menu_show (message->show_menu.window, - message->show_menu.root_x, - message->show_menu.root_y, - message->show_menu.button, - message->show_menu.ops, - message->show_menu.insensitive, - message->show_menu.timestamp); - break; - - case MetaMessageHideWindowMenuCode: - meta_window_menu_hide (); - break; - - default: - meta_ui_warning ("Unhandled message code %d\n", - message->header.message_code); - break; - } -} - -void -meta_ui_warning (const char *format, ...) -{ - va_list args; - gchar *str; - - g_return_if_fail (format != NULL); - - va_start (args, format); - str = g_strdup_vprintf (format, args); - va_end (args); - - fputs (str, stderr); - fflush (stderr); /* though stderr is unbuffered right */ - - g_free (str); -} - - -#if 0 -{ - int i; - /* Try breaking message queue system. */ - i = 0; - while (i < 1500) - { - meta_message_send_check (); - - if (g_random_boolean ()) - { - int j; - if (g_random_boolean ()) - j = g_random_int_range (0, 15); - else - j = g_random_int_range (0, 1000); - while (j > 0) - { - char b; - b = g_random_int_range (0, 256); - - write (1, &b, 1); - --j; - } - } - - ++i; - } -} -#endif - diff --git a/src/uislave/main.h b/src/uislave/main.h deleted file mode 100644 index 1c21a253a..000000000 --- a/src/uislave/main.h +++ /dev/null @@ -1,32 +0,0 @@ -/* Metacity UI slave main() */ - -/* - * Copyright (C) 2001 Havoc Pennington - * - * 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. - */ - -#ifndef META_UI_MAIN_H -#define META_UI_MAIN_H - -void meta_ui_warning (const char *format, ...); - -/* FIXME */ -#define _(x) x -#define N_(x) x - - -#endif diff --git a/src/uislave/menu.c b/src/uislave/menu.c deleted file mode 100644 index 1cb4f973a..000000000 --- a/src/uislave/menu.c +++ /dev/null @@ -1,486 +0,0 @@ -/* Metacity window menu */ - -/* - * Copyright (C) 2001 Havoc Pennington - * - * 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. - */ - -#include "menu.h" -#include "main.h" -#include -#include - -#define _NET_WM_STATE_REMOVE 0 /* remove/unset property */ -#define _NET_WM_STATE_ADD 1 /* add/set property */ -#define _NET_WM_STATE_TOGGLE 2 /* toggle property */ - -typedef struct _MenuItem MenuItem; -typedef struct _MenuData MenuData; - -struct _MenuItem -{ - MetaMessageWindowMenuOps op; - const char *stock_id; - const char *label; -}; - - -struct _MenuData -{ - GdkWindow *window; - MetaMessageWindowMenuOps op; -}; - -static void activate_cb (GtkWidget *menuitem, gpointer data); - -static GtkWidget *menu = NULL; -static MenuItem menuitems[] = { - { META_MESSAGE_MENU_DELETE, GTK_STOCK_CLOSE, N_("_Close") }, - { META_MESSAGE_MENU_MINIMIZE, NULL, N_("_Minimize") }, - { META_MESSAGE_MENU_MAXIMIZE, NULL, N_("Ma_ximize") }, - { META_MESSAGE_MENU_UNMAXIMIZE, NULL, N_("_Unmaximize") }, - { META_MESSAGE_MENU_SHADE, NULL, N_("_Shade") }, - { META_MESSAGE_MENU_UNSHADE, NULL, N_("U_nshade") }, - { 0, NULL, NULL }, /* separator */ - { META_MESSAGE_MENU_STICK, NULL, N_("Put on _All Workspaces") }, - { META_MESSAGE_MENU_UNSTICK, NULL, N_("Only on _This Workspace") } -}; - -static void -popup_position_func (GtkMenu *menu, - gint *x, - gint *y, - gboolean *push_in, - gpointer user_data) -{ - GtkRequisition req; - GdkPoint *pos; - - pos = user_data; - - gtk_widget_size_request (GTK_WIDGET (menu), &req); - - *x = pos->x; - *y = pos->y; - - /* Ensure onscreen */ - *x = CLAMP (*x, 0, MAX (0, gdk_screen_width () - req.width)); - *y = CLAMP (*y, 0, MAX (0, gdk_screen_height () - req.height)); -} - -static gint -get_num_desktops (void) -{ - Atom type; - gint format; - gulong nitems; - gulong bytes_after; - gulong *num; - int result; - - XGetWindowProperty (gdk_display, gdk_root_window, - gdk_atom_intern ("_NET_NUMBER_OF_DESKTOPS", FALSE), - 0, G_MAXLONG, - False, XA_CARDINAL, &type, &format, &nitems, - &bytes_after, (guchar **)&num); - - if (type != XA_CARDINAL) - return 0; - - result = *num; - - XFree (num); - - return result; -} - -static gint -get_active_desktop (void) -{ - Atom type; - gint format; - gulong nitems; - gulong bytes_after; - gulong *num; - int result; - - XGetWindowProperty (gdk_display, gdk_root_window, - gdk_atom_intern ("_NET_CURRENT_DESKTOP", FALSE), - 0, G_MAXLONG, - False, XA_CARDINAL, &type, &format, &nitems, - &bytes_after, (guchar **)&num); - - if (type != XA_CARDINAL) - return 0; - - result = *num; - - XFree (num); - - return result; -} - -static gulong -get_current_desktop (GdkWindow *window) -{ - Atom type; - gint format; - gulong nitems; - gulong bytes_after; - gulong *num; - gulong result; - int err; - - gdk_error_trap_push (); - type = None; - XGetWindowProperty (gdk_display, GDK_WINDOW_XID (window), - gdk_atom_intern ("_NET_WM_DESKTOP", FALSE), - 0, G_MAXLONG, - False, XA_CARDINAL, &type, &format, &nitems, - &bytes_after, (guchar **)&num); - err = gdk_error_trap_pop (); - if (err != Success) - meta_ui_warning ("Error %d getting _NET_WM_DESKTOP\n", err); - - if (type != XA_CARDINAL) - { - meta_ui_warning ("_NET_WM_DESKTOP has wrong type %s\n", gdk_atom_name (type)); - return 0xFFFFFFFF; /* sticky */ - } - - result = *num; - - XFree (num); - - return result; -} - -void -meta_window_menu_show (gulong xwindow, - int root_x, int root_y, - int button, - MetaMessageWindowMenuOps ops, - MetaMessageWindowMenuOps insensitive, - guint32 timestamp) -{ - int i; - GdkWindow *window; - GdkPoint *pt; - int n_workspaces; - int current_workspace; - - if (menu) - gtk_widget_destroy (menu); - - window = gdk_xid_table_lookup (xwindow); - if (window) - g_object_ref (G_OBJECT (window)); - else - window = gdk_window_foreign_new (xwindow); - - /* X error creating the foreign window means NULL here */ - if (window == NULL) - return; - - menu = gtk_menu_new (); - - i = 0; - while (i < G_N_ELEMENTS (menuitems)) - { - if (ops & menuitems[i].op || menuitems[i].op == 0) - { - GtkWidget *mi; - MenuData *md; - - if (menuitems[i].op == 0) - { - mi = gtk_separator_menu_item_new (); - } - else - { - if (menuitems[i].stock_id) - { - GtkWidget *image; - - mi = gtk_image_menu_item_new_with_mnemonic (menuitems[i].label); - image = gtk_image_new_from_stock (menuitems[i].stock_id, - GTK_ICON_SIZE_MENU); - gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (mi), - image); - gtk_widget_show (image); - } - else - { - mi = gtk_menu_item_new_with_mnemonic (menuitems[i].label); - } - - if (insensitive & menuitems[i].op) - gtk_widget_set_sensitive (mi, FALSE); - - md = g_new (MenuData, 1); - - md->window = window; - md->op = menuitems[i].op; - - gtk_signal_connect (GTK_OBJECT (mi), - "activate", - GTK_SIGNAL_FUNC (activate_cb), - md); - } - - gtk_menu_shell_append (GTK_MENU_SHELL (menu), - mi); - - gtk_widget_show (mi); - } - ++i; - } - - if (ops & META_MESSAGE_MENU_WORKSPACES) - { - n_workspaces = get_num_desktops (); - current_workspace = get_current_desktop (window); - - meta_ui_warning ("Creating %d workspace menu current %d\n", - n_workspaces, current_workspace); - - if (n_workspaces > 0) - { - GtkWidget *mi; - - i = 0; - while (i < n_workspaces) - { - char *label; - MenuData *md; - - if (current_workspace == 0xFFFFFFFF) - label = g_strdup_printf (_("Only on workspace _%d\n"), - i + 1); - else - label = g_strdup_printf (_("Move to workspace _%d\n"), - i + 1); - - mi = gtk_menu_item_new_with_mnemonic (label); - - g_free (label); - - if (current_workspace == i || - insensitive & META_MESSAGE_MENU_WORKSPACES) - gtk_widget_set_sensitive (mi, FALSE); - - md = g_new (MenuData, 1); - - md->window = window; - md->op = META_MESSAGE_MENU_WORKSPACES; - - g_object_set_data (G_OBJECT (mi), - "workspace", - GINT_TO_POINTER (i)); - - gtk_signal_connect (GTK_OBJECT (mi), - "activate", - GTK_SIGNAL_FUNC (activate_cb), - md); - - gtk_menu_shell_append (GTK_MENU_SHELL (menu), - mi); - - gtk_widget_show (mi); - - ++i; - } - } - } - else - meta_ui_warning ("not creating workspace menu\n"); - - gtk_signal_connect (GTK_OBJECT (menu), - "destroy", - GTK_SIGNAL_FUNC (gtk_widget_destroyed), - &menu); - - pt = g_new (GdkPoint, 1); - - g_object_set_data_full (G_OBJECT (menu), - "destroy-point", - pt, - g_free); - - pt->x = root_x; - pt->y = root_y; - - gtk_menu_popup (GTK_MENU (menu), - NULL, NULL, - popup_position_func, pt, - button, - timestamp); - - if (!GTK_MENU_SHELL (menu)->have_xgrab) - meta_ui_warning ("GtkMenu failed to grab the pointer\n"); -} - -void -meta_window_menu_hide (void) -{ - if (menu) - gtk_widget_destroy (menu); -} - -static void -close_window (GdkWindow *window) -{ - XClientMessageEvent ev; - - ev.type = ClientMessage; - ev.window = GDK_WINDOW_XID (window); - ev.message_type = gdk_atom_intern ("_NET_CLOSE_WINDOW", FALSE); - ev.format = 32; - ev.data.l[0] = 0; - ev.data.l[1] = 0; - - gdk_error_trap_push (); - XSendEvent (gdk_display, - gdk_root_window, False, - SubstructureNotifyMask | SubstructureRedirectMask, - (XEvent*) &ev); - gdk_flush (); - gdk_error_trap_pop (); -} - -static void -wmspec_change_state (gboolean add, - GdkWindow *window, - GdkAtom state1, - GdkAtom state2) -{ - XEvent xev; - gulong op; - - if (add) - op = _NET_WM_STATE_ADD; - else - op = _NET_WM_STATE_REMOVE; - - xev.xclient.type = ClientMessage; - xev.xclient.serial = 0; - xev.xclient.send_event = True; - xev.xclient.display = gdk_display; - xev.xclient.window = GDK_WINDOW_XID (window); - xev.xclient.message_type = gdk_atom_intern ("_NET_WM_STATE", FALSE); - xev.xclient.format = 32; - xev.xclient.data.l[0] = op; - xev.xclient.data.l[1] = state1; - xev.xclient.data.l[2] = state2; - - XSendEvent (gdk_display, gdk_root_window, False, - SubstructureRedirectMask | SubstructureNotifyMask, - &xev); -} - -static void -wmspec_change_desktop (GdkWindow *window, - gint desktop) -{ - XEvent xev; - - xev.xclient.type = ClientMessage; - xev.xclient.serial = 0; - xev.xclient.send_event = True; - xev.xclient.display = gdk_display; - xev.xclient.window = GDK_WINDOW_XID (window); - xev.xclient.message_type = gdk_atom_intern ("_NET_WM_DESKTOP", FALSE); - xev.xclient.format = 32; - xev.xclient.data.l[0] = desktop; - xev.xclient.data.l[1] = 0; - xev.xclient.data.l[2] = 0; - - XSendEvent (gdk_display, gdk_root_window, False, - SubstructureRedirectMask | SubstructureNotifyMask, - &xev); -} - -static void -activate_cb (GtkWidget *menuitem, gpointer data) -{ - MenuData *md; - - md = data; - - switch (md->op) - { - case META_MESSAGE_MENU_DELETE: - close_window (md->window); - break; - - case META_MESSAGE_MENU_MINIMIZE: - gdk_window_iconify (md->window); - break; - - case META_MESSAGE_MENU_UNMAXIMIZE: - wmspec_change_state (FALSE, md->window, - gdk_atom_intern ("_NET_WM_STATE_MAXIMIZED_HORZ", FALSE), - gdk_atom_intern ("_NET_WM_STATE_MAXIMIZED_VERT", FALSE)); - break; - - case META_MESSAGE_MENU_MAXIMIZE: - wmspec_change_state (TRUE, md->window, - gdk_atom_intern ("_NET_WM_STATE_MAXIMIZED_HORZ", FALSE), - gdk_atom_intern ("_NET_WM_STATE_MAXIMIZED_VERT", FALSE)); - break; - - case META_MESSAGE_MENU_UNSHADE: - wmspec_change_state (FALSE, md->window, - gdk_atom_intern ("_NET_WM_STATE_SHADED", FALSE), - 0); - break; - - case META_MESSAGE_MENU_SHADE: - wmspec_change_state (TRUE, md->window, - gdk_atom_intern ("_NET_WM_STATE_SHADED", FALSE), - 0); - break; - - case META_MESSAGE_MENU_WORKSPACES: - { - int workspace; - - workspace = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (menuitem), - "workspace")); - - wmspec_change_desktop (md->window, workspace); - } - break; - - case META_MESSAGE_MENU_STICK: - wmspec_change_desktop (md->window, 0xFFFFFFFF); - break; - - case META_MESSAGE_MENU_UNSTICK: - wmspec_change_desktop (md->window, get_active_desktop ()); - break; - - default: - meta_ui_warning (G_STRLOC": Unknown window op\n"); - break; - } - - if (menu) - gtk_widget_destroy (menu); - g_object_unref (G_OBJECT (md->window)); - g_free (md); -} diff --git a/src/uislave/menu.h b/src/uislave/menu.h deleted file mode 100644 index 8a667781c..000000000 --- a/src/uislave/menu.h +++ /dev/null @@ -1,39 +0,0 @@ -/* Metacity window menu */ - -/* - * Copyright (C) 2001 Havoc Pennington - * - * 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. - */ - -#ifndef META_MENU_H -#define META_MENU_H - -#include -#include "messages.h" -void meta_window_menu_show (gulong xwindow, - int root_x, - int root_y, - int button, - MetaMessageWindowMenuOps ops, - MetaMessageWindowMenuOps insensitive, - guint32 timestamp); -void meta_window_menu_hide (void); - - - - -#endif diff --git a/src/uislave/messagequeue.c b/src/uislave/messagequeue.c deleted file mode 100644 index 73bcc2971..000000000 --- a/src/uislave/messagequeue.c +++ /dev/null @@ -1,564 +0,0 @@ -/* Metacity IPC message source for main loop */ - -/* - * Copyright (C) 2001 Havoc Pennington - * - * 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. - */ - -#include "messagequeue.h" -#include -#include -#include -#include - -#ifdef METACITY_COMPILE -#include "util.h" -#else -#include "main.h" -void -meta_debug_spew (const char *format, ...) -{ -} - -void -meta_verbose (const char *format, ...) -{ -} - -void -meta_bug (const char *format, ...) -{ - /* stop us in a debugger */ - abort (); -} - -void -meta_warning (const char *format, ...) -{ -} - -void -meta_fatal (const char *format, ...) -{ - exit (1); -} -#endif /* !METACITY_COMPILE */ - -typedef enum -{ - READ_FAILED = 0, /* FALSE */ - READ_OK, - READ_EOF -} ReadResult; - -static ReadResult read_data (GString *str, - gint fd); - -/* Message queue main loop source */ -static gboolean mq_prepare (GSource *source, - gint *timeout); -static gboolean mq_check (GSource *source); -static gboolean mq_dispatch (GSource *source, - GSourceFunc callback, - gpointer user_data); -static void mq_destroy (GSource *source); - -static GSourceFuncs mq_funcs = { - mq_prepare, - mq_check, - mq_dispatch, - mq_destroy -}; - -struct _MetaMessageQueue -{ - GSource source; - - GPollFD out_poll; - GQueue *queue; - GString *buf; - GString *current_message; - int current_required_len; - int last_serial; -}; - -MetaMessageQueue* -meta_message_queue_new (int fd, - MetaMessageQueueFunc func, - gpointer data) -{ - MetaMessageQueue *mq; - GSource *source; - - source = g_source_new (&mq_funcs, sizeof (MetaMessageQueue)); - - mq = (MetaMessageQueue*) source; - - mq->queue = g_queue_new (); - mq->buf = g_string_new (""); - mq->current_message = g_string_new (""); - mq->current_required_len = 0; - mq->last_serial = 0; - mq->out_poll.fd = fd; - mq->out_poll.events = G_IO_IN; - - g_source_add_poll (source, &mq->out_poll); - - g_source_set_priority (source, G_PRIORITY_DEFAULT); - g_source_set_can_recurse (source, TRUE); - - g_source_set_callback (source, (GSourceFunc) func, data, NULL); - - g_source_attach (source, NULL); - - return mq; -} - -void -meta_message_queue_free (MetaMessageQueue *mq) -{ - GSource *source; - - source = (GSource*) mq; - - g_source_destroy (source); -} - -static void -append_pending (MetaMessageQueue *mq) -{ - int needed; - - needed = mq->current_required_len - mq->current_message->len; - g_assert (needed >= 0); - - needed = MIN (needed, mq->buf->len); - - /* Move data from buf to current_message */ - if (needed > 0) - { - meta_verbose ("Moving %d bytes from buffer to current incomplete message\n", - needed); - g_string_append_len (mq->current_message, - mq->buf->str, - needed); - g_string_erase (mq->buf, - 0, needed); - } - - g_assert (mq->current_message->len <= mq->current_required_len); - - if (mq->current_required_len > 0 && - mq->current_message->len == mq->current_required_len) - { - MetaMessage *message; - MetaMessageFooter *footer; - - message = g_new (MetaMessage, 1); - - memcpy (message, - mq->current_message->str, mq->current_message->len); - - if (message->header.length != mq->current_required_len) - meta_bug ("Message length changed?\n"); - - if (message->header.serial != mq->last_serial) - meta_bug ("Message serial changed?\n"); - - footer = META_MESSAGE_FOOTER (message); - - if (footer->checksum == META_MESSAGE_CHECKSUM (message)) - { - g_queue_push_tail (mq->queue, message); - - meta_verbose ("Added %d-byte message serial %d to queue\n", - mq->current_message->len, message->header.serial); - } - else - { - meta_bug ("Bad checksum %d on %d-byte message from UI slave\n", - footer->checksum, mq->current_message->len); - } - - mq->current_required_len = 0; - g_string_truncate (mq->current_message, 0); - } - else if (mq->current_required_len > 0) - { - meta_verbose ("Storing %d bytes of incomplete message\n", - mq->current_message->len); - } -} - -static void -mq_queue_messages (MetaMessageQueue *mq) -{ - while (mq->buf->len > 0) - { - if (mq->current_required_len > 0) - { - /* We had a pending message. */ - append_pending (mq); - } - else if (mq->buf->len > META_MESSAGE_ESCAPE_LEN) - { - /* See if we can start a current message */ - const char *p; - int esc_pos; - const char *esc; - MetaMessageHeader header; - - g_assert (mq->current_required_len == 0); - g_assert (mq->current_message->len == 0); - - meta_verbose ("Scanning for escape sequence in %d bytes\n", - mq->buf->len); - - /* note that the data from the UI slave includes the nul byte */ - esc = META_MESSAGE_ESCAPE; - - esc_pos = -1; - p = mq->buf->str; - while (p != (mq->buf->str + mq->buf->len)) - { - if (*p == *esc) - { - esc_pos = 0; - while (*p == esc[esc_pos]) - { - ++esc_pos; - ++p; - - if (esc_pos == META_MESSAGE_ESCAPE_LEN || - p == (mq->buf->str + mq->buf->len)) - goto out; - } - - esc_pos = -1; - } - else - { - ++p; - } - } - - out: - if (esc_pos == META_MESSAGE_ESCAPE_LEN) - { - /* We found an entire escape sequence; can safely toss - * out the entire buffer before it - */ - int ignored; - - g_assert (esc[META_MESSAGE_ESCAPE_LEN-1] == *(p-1)); - - ignored = p - mq->buf->str; - ignored -= META_MESSAGE_ESCAPE_LEN; - - g_assert (ignored >= 0); - g_assert (mq->buf->str[ignored] == esc[0]); - - if (ignored > 0) - { - g_string_erase (mq->buf, 0, ignored); - meta_verbose ("Ignoring %d bytes before escape, new buffer len %d\n", - ignored, mq->buf->len); - } - else - { - g_assert (p == (mq->buf->str + META_MESSAGE_ESCAPE_LEN)); - } - } - else if (esc_pos < 0) - { - /* End of buffer doesn't begin an escape sequence; - * toss out entire buffer. - */ - meta_verbose ("Emptying %d-byte buffer not containing escape sequence\n", - mq->buf->len); - g_string_truncate (mq->buf, 0); - goto need_more_data; - } - else - { - meta_verbose ("Buffer ends with partial escape sequence\n"); - goto need_more_data; - } - - g_assert (strcmp (mq->buf->str, META_MESSAGE_ESCAPE) == 0); - - if (mq->buf->len < (META_MESSAGE_ESCAPE_LEN + sizeof (MetaMessageHeader))) - { - meta_verbose ("Buffer has full escape sequence but lacks header\n"); - goto need_more_data; - } - - g_string_erase (mq->buf, 0, META_MESSAGE_ESCAPE_LEN); - meta_verbose ("Stripped escape off front of buffer, new buffer len %d\n", - mq->buf->len); - - g_assert (mq->buf->len >= sizeof (MetaMessageHeader)); - - memcpy (&header, mq->buf->str, sizeof (MetaMessageHeader)); - - /* Length includes the header even though it's in the header. */ - meta_verbose ("Read header, code: %d length: %d serial: %d\n", - header.message_code, header.length, header.serial); - - if (header.serial != mq->last_serial + 1) - meta_bug ("Wrong message serial number %d from UI slave!\n", header.serial); - - mq->last_serial = header.serial; - mq->current_required_len = header.length; - - append_pending (mq); - } - else - goto need_more_data; - } - - need_more_data: - return; -} - -static gboolean -mq_messages_pending (MetaMessageQueue *mq) -{ - return mq->queue->length > 0; - /* these are useless until we wake up on poll again */ -#if 0 - mq->buf->len > 0 || - mq->current_message->len > 0; -#endif -} - -static gboolean -mq_prepare (GSource *source, gint *timeout) -{ - MetaMessageQueue *mq; - - mq = (MetaMessageQueue*) source; - - *timeout = -1; - - mq_queue_messages (mq); - - return mq_messages_pending (mq); -} - -static gboolean -mq_check (GSource *source) -{ - MetaMessageQueue *mq; - - mq = (MetaMessageQueue*) source; - - mq_queue_messages (mq); - - if (mq->out_poll.revents & G_IO_IN) - { - ReadResult res; - - res = read_data (mq->buf, mq->out_poll.fd); - - switch (res) - { - case READ_OK: - meta_verbose ("Read data from slave, %d bytes in buffer\n", - mq->buf->len); - break; - case READ_EOF: -#ifdef METACITY_COMPILE - meta_verbose ("EOF reading stdout from slave process\n"); -#else - meta_ui_warning ("Metacity parent process disappeared\n"); - exit (1); -#endif - break; - - case READ_FAILED: - /* read_data printed the error */ - break; - } - } - - - if (mq->out_poll.revents & G_IO_HUP) - { -#ifdef METACITY_COMPILE - meta_verbose ("UI slave hung up\n"); -#else - meta_ui_warning ("Metacity parent process hung up\n"); - exit (1); -#endif - } - - mq->out_poll.revents = 0; - - return mq_messages_pending (mq); -} - -static gboolean -mq_dispatch (GSource *source, GSourceFunc callback, gpointer user_data) -{ - MetaMessageQueue *mq; - - mq = (MetaMessageQueue*) source; - - if (mq->queue->length > 0) - { - MetaMessageQueueFunc func; - MetaMessage *msg; - static int count = 0; - - ++count; - - msg = g_queue_pop_head (mq->queue); - func = (MetaMessageQueueFunc) callback; - - (* func) (mq, msg, user_data); - - meta_verbose ("%d messages dispatched\n", count); - - g_free (msg); - } - - return TRUE; -} - -static void -mq_destroy (GSource *source) -{ - MetaMessageQueue *mq; - - mq = (MetaMessageQueue*) source; - - while (mq->queue->length > 0) - { - MetaMessage *msg; - - msg = g_queue_pop_head (mq->queue); - - g_free (msg); - } - - g_string_free (mq->buf, TRUE); - g_string_free (mq->current_message, TRUE); - - g_queue_free (mq->queue); - - /* source itself is freed by glib */ -} - -static ReadResult -read_data (GString *str, - gint fd) -{ -#define BUFSIZE 1024 - gint bytes; - gchar buf[BUFSIZE]; - - again: - - bytes = read (fd, &buf, BUFSIZE); - - if (bytes == 0) - return READ_EOF; - else if (bytes > 0) - { - g_string_append_len (str, buf, bytes); - return READ_OK; - } - else if (bytes < 0 && errno == EINTR) - goto again; - else if (bytes < 0) - { - meta_warning (_("Failed to read data from UI slave: %s\n"), - g_strerror (errno)); - - return READ_FAILED; - } - else - return READ_OK; -} - -/* Wait forever and build infinite queue until we get - * the desired serial_of_request or one higher than it - */ -void -meta_message_queue_wait_for_reply (MetaMessageQueue *mq, - int serial_of_request) -{ - ReadResult res; - int prev_len; - - prev_len = 0; - while (TRUE) - { - if (prev_len < mq->queue->length) - { - GList *tmp; - - tmp = g_list_nth (mq->queue->head, prev_len); - while (tmp != NULL) - { - MetaMessage *msg = tmp->data; - - if (msg->header.request_serial == serial_of_request) - return; - - if (msg->header.request_serial > serial_of_request) - { - meta_warning ("Serial request %d is greater than the awaited request %d\n", - msg->header.request_serial, serial_of_request); - return; - } - - tmp = tmp->next; - } - - prev_len = mq->queue->length; - } - - res = read_data (mq->buf, mq->out_poll.fd); - - switch (res) - { - case READ_OK: - meta_verbose ("Read data from slave, %d bytes in buffer\n", - mq->buf->len); - break; - - case READ_EOF: -#ifdef METACITY_COMPILE - meta_verbose ("EOF reading stdout from slave process\n"); -#else - meta_ui_warning ("Metacity parent process disappeared\n"); - exit (1); -#endif - return; - break; - - case READ_FAILED: - /* read_data printed the error */ - return; - break; - } - - mq_queue_messages (mq); - } -} diff --git a/src/uislave/messagequeue.h b/src/uislave/messagequeue.h deleted file mode 100644 index a3c9cd99f..000000000 --- a/src/uislave/messagequeue.h +++ /dev/null @@ -1,47 +0,0 @@ -/* Metacity IPC message source for main loop */ - -/* - * Copyright (C) 2001 Havoc Pennington - * - * 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. - */ - -#ifndef META_MESSAGE_QUEUE_H -#define META_MESSAGE_QUEUE_H - -#include - -#ifdef METACITY_COMPILE -#include "uislave/messages.h" -#else -#include "messages.h" -#endif - -typedef struct _MetaMessageQueue MetaMessageQueue; - -typedef void (* MetaMessageQueueFunc) (MetaMessageQueue *mq, - MetaMessage *message, - gpointer data); - -MetaMessageQueue* meta_message_queue_new (int fd, - MetaMessageQueueFunc func, - gpointer data); -void meta_message_queue_free (MetaMessageQueue *mq); - -void meta_message_queue_wait_for_reply (MetaMessageQueue *mq, - int serial_of_request); - -#endif diff --git a/src/uislave/messages.c b/src/uislave/messages.c deleted file mode 100644 index ff975e5ad..000000000 --- a/src/uislave/messages.c +++ /dev/null @@ -1,173 +0,0 @@ -/* Metacity UI Slave Messages */ - -/* - * Copyright (C) 2001 Havoc Pennington - * - * 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. - */ - -#include "messages.h" -#include "main.h" - -#include -#include -#include -#include -#include -#include -#include - -typedef enum -{ - READ_FAILED = 0, /* FALSE */ - READ_OK, - READ_EOF -} ReadResult; - -static ReadResult read_data (GString *str, - gint fd); - -static void send_message (MetaMessage *message, - int request_serial); - -void -meta_message_send_check (void) -{ - MetaMessageCheck check; - - memset (&check, 0, META_MESSAGE_LENGTH (MetaMessageCheck)); - check.header.message_code = MetaMessageCheckCode; - check.header.length = META_MESSAGE_LENGTH (MetaMessageCheck); - - strncpy (check.metacity_version, VERSION, META_MESSAGE_MAX_VERSION_LEN); - check.metacity_version[META_MESSAGE_MAX_VERSION_LEN] = '\0'; - - strncpy (check.host_alias, HOST_ALIAS, META_MESSAGE_MAX_HOST_ALIAS_LEN); - check.host_alias[META_MESSAGE_MAX_HOST_ALIAS_LEN] = '\0'; - - check.messages_version = META_MESSAGES_VERSION; - - send_message ((MetaMessage*)&check, 0); -} - -static int -write_bytes (void *buf, int bytes) -{ - const char *p; - int left; - - left = bytes; - p = (char*) buf; - while (left > 0) - { - int written; - - written = write (1, p, left); - - if (written < 0) - return -1; - - left -= written; - p += written; - } - - g_assert (p == ((char*)buf) + bytes); - - return 0; -} - -#if 0 -static void -print_mem (int fd, void *mem, int len) -{ - char *p = (char*) mem; - int i; - char unknown = 'Z'; - char null = 'n'; - - i = 0; - while (i < len) - { - if (p[i] == '\0') - write (fd, &null, 1); - else if (isascii (p[i])) - write (fd, p + i, 1); - else - write (fd, &unknown, 1); - - ++i; - } -} -#endif - -static void -send_message (MetaMessage *message, - int request_serial) -{ - static int serial = 1; - MetaMessageFooter *footer; - - message->header.serial = serial; - message->header.request_serial = request_serial; - footer = META_MESSAGE_FOOTER (message); - - footer->checksum = META_MESSAGE_CHECKSUM (message); - ++serial; - -#if 0 - meta_ui_warning ("'"); - print_mem (2, message, message->header.length); - meta_ui_warning ("'\n"); -#endif - - if (write_bytes (META_MESSAGE_ESCAPE, META_MESSAGE_ESCAPE_LEN) < 0) - meta_ui_warning ("Failed to write escape sequence: %s\n", - g_strerror (errno)); - if (write_bytes (message, message->header.length) < 0) - meta_ui_warning ("Failed to write message: %s\n", - g_strerror (errno)); -} - -static ReadResult -read_data (GString *str, - gint fd) -{ - gint bytes; - gchar buf[4096]; - - again: - - bytes = read (fd, &buf, 4096); - - if (bytes == 0) - return READ_EOF; - else if (bytes > 0) - { - g_string_append_len (str, buf, bytes); - return READ_OK; - } - else if (bytes < 0 && errno == EINTR) - goto again; - else if (bytes < 0) - { - meta_ui_warning (_("Failed to read data from window manager (%s)\n"), - g_strerror (errno)); - - return READ_FAILED; - } - else - return READ_OK; -} diff --git a/src/uislave/messages.h b/src/uislave/messages.h deleted file mode 100644 index 453e50339..000000000 --- a/src/uislave/messages.h +++ /dev/null @@ -1,216 +0,0 @@ -/* Metacity UI Slave Messages */ - -/* - * Copyright (C) 2001 Havoc Pennington - * - * 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. - */ - -#ifndef META_UI_SLAVE_MESSAGES_H -#define META_UI_SLAVE_MESSAGES_H - -#include - -/* General shared types */ - -typedef enum -{ - META_FRAME_ALLOWS_DELETE = 1 << 0, - META_FRAME_ALLOWS_MENU = 1 << 1, - META_FRAME_ALLOWS_MINIMIZE = 1 << 2, - META_FRAME_ALLOWS_MAXIMIZE = 1 << 3, - META_FRAME_ALLOWS_RESIZE = 1 << 4, - META_FRAME_TRANSIENT = 1 << 5, - META_FRAME_HAS_FOCUS = 1 << 6, - META_FRAME_SHADED = 1 << 7, - META_FRAME_STUCK = 1 << 8 -} MetaFrameFlags; - -typedef enum -{ - META_FRAME_CONTROL_NONE, - META_FRAME_CONTROL_TITLE, - META_FRAME_CONTROL_DELETE, - META_FRAME_CONTROL_MENU, - META_FRAME_CONTROL_MINIMIZE, - META_FRAME_CONTROL_MAXIMIZE, - META_FRAME_CONTROL_RESIZE_SE, - META_FRAME_CONTROL_RESIZE_S, - META_FRAME_CONTROL_RESIZE_SW, - META_FRAME_CONTROL_RESIZE_N, - META_FRAME_CONTROL_RESIZE_NE, - META_FRAME_CONTROL_RESIZE_NW, - META_FRAME_CONTROL_RESIZE_W, - META_FRAME_CONTROL_RESIZE_E -} MetaFrameControl; - - - -/* Now the IPC mess */ - -/* This thing badly violates the KISS principle. */ - -/* This header is shared between the WM and the UI slave */ -/* Note that our IPC can be kind of lame; we trust both sides - * of the connection, and assume that they were compiled at the - * same time vs. the same libs on the same arch - */ -/* (and lo and behold, our IPC is kind of lame) */ - -/* We increment this when we change this header, so we can - * check for mismatched UI slave and WM - */ -#define META_MESSAGES_VERSION 2 - -/* We have an escape sequence, just in case some part of GTK - * decides to write to stdout, so that we have a good chance - * of surviving that. GTK probably won't print this string. - * This string has to stay the same always so we can ping - * old UI slaves. - */ -#define META_MESSAGE_ESCAPE "|~-metacity-~|" -/* len includes nul byte which is a required part of the escape */ -#define META_MESSAGE_ESCAPE_LEN 15 - -/* This is totally useless of course. Playing around. */ -#define META_MESSAGE_CHECKSUM(msg) ((msg)->header.length | (msg)->header.serial << 16) -#define META_MESSAGE_FOOTER(msg) ((MetaMessageFooter*) (((char*)(msg)) + ((msg)->header.length - sizeof (MetaMessageFooter)))); -#define META_MESSAGE_LENGTH(real_type) \ - (G_STRUCT_OFFSET (real_type, footer) + sizeof (MetaMessageFooter)) - -#define META_MESSAGE_MAX_SIZE (sizeof(MetaMessage)); - -#define META_MESSAGE_MAX_VERSION_LEN 15 -#define META_MESSAGE_MAX_HOST_ALIAS_LEN 50 -#define META_MESSAGE_MAX_TIP_LEN 128 - -typedef union _MetaMessage MetaMessage; -typedef struct _MetaMessageHeader MetaMessageHeader; -typedef struct _MetaMessageFooter MetaMessageFooter; -typedef struct _MetaMessageCheck MetaMessageCheck; -typedef struct _MetaMessageShowTip MetaMessageShowTip; -typedef struct _MetaMessageHideTip MetaMessageHideTip; -typedef struct _MetaMessageShowWindowMenu MetaMessageShowWindowMenu; -typedef struct _MetaMessageHideWindowMenu MetaMessageHideWindowMenu; - -typedef enum -{ - /* Keep NullCode and CheckCode unchanged, as with the escape sequence, - * so we can check old UI slaves. - */ - MetaMessageNullCode, - MetaMessageCheckCode, - MetaMessageShowTipCode, - MetaMessageHideTipCode, - MetaMessageShowWindowMenuCode, - MetaMessageHideWindowMenuCode -} MetaMessageCode; - -struct _MetaMessageHeader -{ - MetaMessageCode message_code; - int length; - int serial; - int request_serial; /* 0 if none */ -}; - -/* The footer thing was pretty much just a debug hack and could die. */ -struct _MetaMessageFooter -{ - int checksum; -}; - -/* just a ping to see if we have the right - * version of UI slave. - */ -struct _MetaMessageCheck -{ - MetaMessageHeader header; - - /* it's OK if the max sizes aren't large enough in all cases, these - * are just paranoia checks - */ - char metacity_version[META_MESSAGE_MAX_VERSION_LEN + 1]; - char host_alias[META_MESSAGE_MAX_HOST_ALIAS_LEN + 1]; - int messages_version; - - MetaMessageFooter footer; -}; - -struct _MetaMessageShowTip -{ - MetaMessageHeader header; - int root_x; - int root_y; - char markup[META_MESSAGE_MAX_TIP_LEN + 1]; - MetaMessageFooter footer; -}; - -struct _MetaMessageHideTip -{ - MetaMessageHeader header; - /* just hides the current tip */ - MetaMessageFooter footer; -}; - -typedef enum -{ - META_MESSAGE_MENU_DELETE = 1 << 0, - META_MESSAGE_MENU_MINIMIZE = 1 << 1, - META_MESSAGE_MENU_UNMAXIMIZE = 1 << 2, - META_MESSAGE_MENU_MAXIMIZE = 1 << 3, - META_MESSAGE_MENU_UNSHADE = 1 << 4, - META_MESSAGE_MENU_SHADE = 1 << 5, - META_MESSAGE_MENU_UNSTICK = 1 << 6, - META_MESSAGE_MENU_STICK = 1 << 7, - META_MESSAGE_MENU_WORKSPACES = 1 << 8 -} MetaMessageWindowMenuOps; - -struct _MetaMessageShowWindowMenu -{ - MetaMessageHeader header; - MetaMessageWindowMenuOps ops; - MetaMessageWindowMenuOps insensitive; - gulong window; - int root_x; - int root_y; - guint32 timestamp; - int button; - MetaMessageFooter footer; -}; - -struct _MetaMessageHideWindowMenu -{ - MetaMessageHeader header; - - MetaMessageFooter footer; -}; - -union _MetaMessage -{ - MetaMessageHeader header; - MetaMessageCheck check; - MetaMessageShowTip show_tip; - MetaMessageShowTip hide_tip; - MetaMessageShowWindowMenu show_menu; - MetaMessageHideWindowMenu hide_menu; -}; - -/* Slave-side message send/read code */ - -void meta_message_send_check (void); - -#endif diff --git a/src/window.c b/src/window.c index 336e9f3c5..44bf39fce 100644 --- a/src/window.c +++ b/src/window.c @@ -77,6 +77,7 @@ static void meta_window_hide (MetaWindow *window); static void meta_window_move_resize_internal (MetaWindow *window, gboolean is_configure_request, + int resize_gravity, int root_x_nw, int root_y_nw, int w, @@ -157,6 +158,19 @@ meta_window_new (MetaDisplay *display, Window xwindow, /* Get rid of any borders */ if (attrs.border_width != 0) XSetWindowBorderWidth (display->xdisplay, xwindow, 0); + + /* Get rid of weird gravities */ + if (attrs.win_gravity != NorthWestGravity) + { + XSetWindowAttributes set_attrs; + + set_attrs.win_gravity = NorthWestGravity; + + XChangeWindowAttributes (display->xdisplay, + xwindow, + CWWinGravity, + &set_attrs); + } if (meta_error_trap_pop (display) != Success) { @@ -420,6 +434,7 @@ meta_window_new (MetaDisplay *display, Window xwindow, * initial map is handled same as configure request */ meta_window_move_resize_internal (window, TRUE, + NorthWestGravity, window->size_hints.x, window->size_hints.y, window->size_hints.width, @@ -1040,6 +1055,7 @@ adjust_for_gravity (MetaWindow *window, static void meta_window_move_resize_internal (MetaWindow *window, gboolean is_configure_request, + int resize_gravity, int root_x_nw, int root_y_nw, int w, @@ -1053,7 +1069,14 @@ meta_window_move_resize_internal (MetaWindow *window, gboolean need_move_frame = FALSE; gboolean need_resize_client = FALSE; gboolean need_resize_frame = FALSE; - + int size_dx; + int size_dy; + int pos_dx; + int pos_dy; + int frame_size_dx; + int frame_size_dy; + int client_gravity; + { int oldx, oldy; meta_window_get_position (window, &oldx, &oldy); @@ -1073,6 +1096,9 @@ meta_window_move_resize_internal (MetaWindow *window, if (w != window->rect.width || h != window->rect.height) need_resize_client = TRUE; + + size_dx = w - window->rect.width; + size_dy = h - window->rect.height; window->rect.width = w; window->rect.height = h; @@ -1091,6 +1117,9 @@ meta_window_move_resize_internal (MetaWindow *window, if (new_w != window->frame->rect.width || new_h != window->frame->rect.height) need_resize_frame = TRUE; + + frame_size_dx = new_w - window->frame->rect.width; + frame_size_dy = new_h - window->frame->rect.height; window->frame->rect.width = new_w; window->frame->rect.height = new_h; @@ -1099,6 +1128,11 @@ meta_window_move_resize_internal (MetaWindow *window, window->frame->rect.width, window->frame->rect.height); } + else + { + frame_size_dx = 0; + frame_size_dy = 0; + } if (is_configure_request) { @@ -1116,6 +1150,39 @@ meta_window_move_resize_internal (MetaWindow *window, meta_verbose ("Compensated position for gravity, new pos %d,%d\n", root_x_nw, root_y_nw); } + + /* There can be somewhat bogus interactions between gravity + * and the position constraints (with position contraints + * basically breaking gravity). Not sure how to fix this. + */ + + /* If client is staying fixed on the east during resize, then we + * have to move the west edge. + */ + switch (resize_gravity) + { + case NorthEastGravity: + case EastGravity: + case SouthEastGravity: + root_x_nw -= size_dx; + break; + default: + break; + } + + /* If client is staying fixed on the south during resize, + * we have to move the north edge + */ + switch (resize_gravity) + { + case SouthGravity: + case SouthEastGravity: + case SouthWestGravity: + root_y_nw -= size_dy; + break; + default: + break; + } constrain_position (window, window->frame ? &fgeom : NULL, @@ -1146,6 +1213,9 @@ meta_window_move_resize_internal (MetaWindow *window, /* window->rect.x, window->rect.y are relative to frame, * remember they are the server coords */ + pos_dx = fgeom.left_width - window->rect.x; + pos_dy = fgeom.top_height - window->rect.y; + window->rect.x = fgeom.left_width; window->rect.y = fgeom.top_height; } @@ -1154,6 +1224,9 @@ meta_window_move_resize_internal (MetaWindow *window, if (root_x_nw != window->rect.x || root_y_nw != window->rect.y) need_move_client = TRUE; + + pos_dx = root_x_nw - window->rect.x; + pos_dy = root_y_nw - window->rect.y; window->rect.x = root_x_nw; window->rect.y = root_y_nw; @@ -1188,8 +1261,10 @@ meta_window_move_resize_internal (MetaWindow *window, !(need_resize_client || need_resize_frame)) need_configure_notify = TRUE; - /* Sync our new size/pos with X as efficiently as possible */ - + /* The rest of this function syncs our new size/pos with X as + * efficiently as possible + */ + values.border_width = 0; values.x = window->rect.x; values.y = window->rect.y; @@ -1227,8 +1302,10 @@ meta_window_move_resize_internal (MetaWindow *window, /* Now do the frame */ if (window->frame) - meta_frame_sync_to_window (window->frame, need_move_frame, need_resize_frame); - + { + meta_frame_sync_to_window (window->frame, need_move_frame, need_resize_frame); + } + if (need_configure_notify) send_configure_notify (window); @@ -1248,7 +1325,9 @@ meta_window_resize (MetaWindow *window, meta_window_get_position (window, &x, &y); - meta_window_move_resize_internal (window, FALSE, x, y, w, h); + meta_window_move_resize_internal (window, FALSE, + NorthWestGravity, + x, y, w, h); } void @@ -1256,7 +1335,8 @@ meta_window_move (MetaWindow *window, int root_x_nw, int root_y_nw) { - meta_window_move_resize_internal (window, FALSE, + meta_window_move_resize_internal (window, FALSE, + NorthWestGravity, root_x_nw, root_y_nw, window->rect.width, window->rect.height); @@ -1270,10 +1350,26 @@ meta_window_move_resize (MetaWindow *window, int h) { meta_window_move_resize_internal (window, FALSE, + NorthWestGravity, root_x_nw, root_y_nw, w, h); } +void +meta_window_resize_with_gravity (MetaWindow *window, + int w, + int h, + int gravity) +{ + int x, y; + + meta_window_get_position (window, &x, &y); + + meta_window_move_resize_internal (window, FALSE, + gravity, + x, y, w, h); +} + void meta_window_move_resize_now (MetaWindow *window) { @@ -1921,6 +2017,7 @@ process_configure_request (MetaWindow *window, window->size_hints.height = height; meta_window_move_resize_internal (window, TRUE, + NorthWestGravity, window->size_hints.x, window->size_hints.y, window->size_hints.width, @@ -3392,3 +3489,23 @@ meta_window_shares_some_workspace (MetaWindow *window, return FALSE; } + +void +meta_window_set_gravity (MetaWindow *window, + int gravity) +{ + XSetWindowAttributes attrs; + + meta_verbose ("Setting gravity of %s to %d\n", window->desc, gravity); + + attrs.win_gravity = gravity; + + meta_error_trap_push (window->display); + + XChangeWindowAttributes (window->display->xdisplay, + window->xwindow, + CWWinGravity, + &attrs); + + meta_error_trap_pop (window->display); +} diff --git a/src/window.h b/src/window.h index 693a662a8..3fd1d0ff9 100644 --- a/src/window.h +++ b/src/window.h @@ -234,6 +234,11 @@ void meta_window_move_resize (MetaWindow *window, int root_y_nw, int w, int h); +void meta_window_resize_with_gravity (MetaWindow *window, + int w, + int h, + int gravity); + /* This recalcs the window/frame size, and recalcs the frame * size/contents as well. */ @@ -278,4 +283,7 @@ void meta_window_show_menu (MetaWindow *window, gboolean meta_window_shares_some_workspace (MetaWindow *window, MetaWindow *with); +void meta_window_set_gravity (MetaWindow *window, + int gravity); + #endif