summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrhp <rhp>2001-06-07 05:18:10 +0000
committerrhp <rhp>2001-06-07 05:18:10 +0000
commit0feac37c5b23870dbd1bdd3ac30e9f5435820217 (patch)
tree0ee727eb83388ec2e99ead6a545da3b6fe492d11
parent834452ca2c2cde16bd11351e90df44cbe20c96bf (diff)
downloadmetacity-0feac37c5b23870dbd1bdd3ac30e9f5435820217.tar.gz
...
-rw-r--r--src/display.c29
-rw-r--r--src/display.h1
-rw-r--r--src/frame.c27
-rw-r--r--src/frame.h3
-rw-r--r--src/menu.c47
-rwxr-xr-xsrc/run-metacity.sh2
-rw-r--r--src/uislave/menu.c47
-rw-r--r--src/window.c113
-rw-r--r--src/window.h19
-rw-r--r--src/workspace.c8
-rw-r--r--src/workspace.h2
11 files changed, 276 insertions, 22 deletions
diff --git a/src/display.c b/src/display.c
index 87a3bfb4..f9fb8ef5 100644
--- a/src/display.c
+++ b/src/display.c
@@ -78,7 +78,8 @@ meta_display_open (const char *name)
"WM_PROTOCOLS",
"WM_TAKE_FOCUS",
"WM_DELETE_WINDOW",
- "WM_STATE"
+ "WM_STATE",
+ "_NET_CLOSE_WINDOW"
};
Atom atoms[G_N_ELEMENTS(atom_names)];
@@ -155,6 +156,7 @@ meta_display_open (const char *name)
display->atom_wm_take_focus = atoms[2];
display->atom_wm_delete_window = atoms[3];
display->atom_wm_state = atoms[4];
+ display->atom_net_close_window = atoms[5];
/* Now manage all existing windows */
tmp = display->screens;
@@ -494,6 +496,18 @@ event_queue_callback (MetaEventQueue *queue,
case ColormapNotify:
break;
case ClientMessage:
+ if (window)
+ {
+ if (event->xclient.message_type ==
+ display->atom_net_close_window)
+ {
+ /* I think the wm spec should maybe put a time
+ * in this message, CurrentTime here is sort of
+ * bogus. But it rarely matters most likely.
+ */
+ meta_window_delete (window, CurrentTime);
+ }
+ }
break;
case MappingNotify:
break;
@@ -708,7 +722,18 @@ meta_spew_event (MetaDisplay *display,
name = "ColormapNotify";
break;
case ClientMessage:
- name = "ClientMessage";
+ {
+ char *str;
+ name = "ClientMessage";
+ meta_error_trap_push (display);
+ str = XGetAtomName (display->xdisplay,
+ event->xclient.message_type);
+ meta_error_trap_pop (display);
+ extra = g_strdup_printf ("type: %s format: %d\n",
+ str ? str : "(unknown atom)",
+ event->xclient.format);
+ XFree (str);
+ }
break;
case MappingNotify:
name = "MappingNotify";
diff --git a/src/display.h b/src/display.h
index 6f092576..4a9df646 100644
--- a/src/display.h
+++ b/src/display.h
@@ -44,6 +44,7 @@ struct _MetaDisplay
Atom atom_wm_take_focus;
Atom atom_wm_delete_window;
Atom atom_wm_state;
+ Atom atom_net_close_window;
/* This is the actual window from focus events,
* not the one we last set
diff --git a/src/frame.c b/src/frame.c
index c10ce98b..fdd69489 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -169,6 +169,8 @@ meta_frame_calc_geometry (MetaFrame *frame,
frame->child_x = geom.left_width;
frame->child_y = geom.top_height;
+ frame->right_width = geom.right_width;
+ frame->bottom_height = geom.bottom_height;
frame->rect.width = frame->rect.width + geom.left_width + geom.right_width;
frame->rect.height = frame->rect.height + geom.top_height + geom.bottom_height;
@@ -787,13 +789,21 @@ meta_frame_event (MetaFrame *frame,
else if (control == META_FRAME_CONTROL_DELETE &&
event->xbutton.button == 1)
{
- /* FIXME delete event */
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)
{
@@ -874,6 +884,21 @@ meta_frame_event (MetaFrame *frame,
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;
diff --git a/src/frame.h b/src/frame.h
index 0b5f2a08..c520b1a2 100644
--- a/src/frame.h
+++ b/src/frame.h
@@ -29,6 +29,7 @@ typedef enum
META_FRAME_ACTION_NONE,
META_FRAME_ACTION_MOVING,
META_FRAME_ACTION_DELETING,
+ META_FRAME_ACTION_TOGGLING_MAXIMIZE,
META_FRAME_ACTION_RESIZING_SE
} MetaFrameAction;
@@ -48,6 +49,8 @@ struct _MetaFrame
MetaRectangle rect;
int child_x;
int child_y;
+ int right_width;
+ int bottom_height;
gpointer theme_data;
gulong bg_pixel;
diff --git a/src/menu.c b/src/menu.c
index 292e9948..81015dd6 100644
--- a/src/menu.c
+++ b/src/menu.c
@@ -176,15 +176,56 @@ meta_window_menu_hide (void)
}
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
activate_cb (GtkWidget *menuitem, gpointer data)
{
MenuData *md;
md = data;
- meta_ui_warning ("Activated menuitem\n");
-
- gtk_widget_destroy (menu);
+ switch (md->op)
+ {
+ case META_MESSAGE_MENU_DELETE:
+ close_window (md->window);
+ break;
+
+ case META_MESSAGE_MENU_MINIMIZE:
+ break;
+
+ case META_MESSAGE_MENU_MAXIMIZE:
+ gdk_error_trap_push ();
+ gdk_window_maximize (md->window);
+ gdk_flush ();
+ gdk_error_trap_pop ();
+ 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/run-metacity.sh b/src/run-metacity.sh
index 40ef0d41..798d711e 100755
--- a/src/run-metacity.sh
+++ b/src/run-metacity.sh
@@ -9,7 +9,7 @@ elif test -z "$DEBUG"; then
DEBUG=gdb
fi
-Xnest :1 -scrns $SCREENS -geometry 270x270 &
+Xnest :1 -scrns $SCREENS -geometry 640x480 &
DISPLAY=:1 xsetroot -solid royalblue3
METACITY_UISLAVE_DIR=./uislave DISPLAY=:1 unst libtool --mode=execute $DEBUG ./metacity
killall Xnest
diff --git a/src/uislave/menu.c b/src/uislave/menu.c
index 292e9948..81015dd6 100644
--- a/src/uislave/menu.c
+++ b/src/uislave/menu.c
@@ -176,15 +176,56 @@ meta_window_menu_hide (void)
}
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
activate_cb (GtkWidget *menuitem, gpointer data)
{
MenuData *md;
md = data;
- meta_ui_warning ("Activated menuitem\n");
-
- gtk_widget_destroy (menu);
+ switch (md->op)
+ {
+ case META_MESSAGE_MENU_DELETE:
+ close_window (md->window);
+ break;
+
+ case META_MESSAGE_MENU_MINIMIZE:
+ break;
+
+ case META_MESSAGE_MENU_MAXIMIZE:
+ gdk_error_trap_push ();
+ gdk_window_maximize (md->window);
+ gdk_flush ();
+ gdk_error_trap_pop ();
+ 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/window.c b/src/window.c
index 4b6a75fd..29dd5c1d 100644
--- a/src/window.c
+++ b/src/window.c
@@ -128,6 +128,9 @@ meta_window_new (MetaDisplay *display, Window xwindow)
window->size_hints.y = attrs.y;
window->size_hints.width = attrs.width;
window->size_hints.height = attrs.height;
+
+ /* And this is our unmaximized size */
+ window->saved_rect = window->rect;
window->depth = attrs.depth;
window->xvisual = attrs.visual;
@@ -139,6 +142,7 @@ meta_window_new (MetaDisplay *display, Window xwindow)
window->frame = NULL;
window->has_focus = FALSE;
+ window->maximized = FALSE;
window->initially_iconic = FALSE;
window->minimized = FALSE;
window->iconic = FALSE;
@@ -198,8 +202,10 @@ meta_window_free (MetaWindow *window)
}
g_assert (window->workspaces == NULL);
+
+ /* FIXME restore original size if window has maximized */
- set_wm_state (window, WithdrawnState);
+ set_wm_state (window, WithdrawnState);
meta_display_unregister_x_window (window->display, window->xwindow);
@@ -319,7 +325,7 @@ meta_window_minimize (MetaWindow *window)
if (!window->minimized)
{
window->minimized = TRUE;
- meta_window_hide (window);
+ meta_window_queue_calc_showing (window);
}
}
@@ -329,7 +335,60 @@ meta_window_unminimize (MetaWindow *window)
if (window->minimized)
{
window->minimized = FALSE;
- meta_window_show (window);
+ meta_window_queue_calc_showing (window);
+ }
+}
+
+void
+meta_window_maximize (MetaWindow *window)
+{
+ if (!window->maximized)
+ {
+ int x, y;
+
+ window->maximized = TRUE;
+
+ /* save size */
+ window->saved_rect = window->rect;
+ if (window->frame)
+ {
+ window->saved_rect.x += window->frame->rect.x;
+ window->saved_rect.y += window->frame->rect.y;
+ }
+
+ /* resize to current size with new maximization constraint */
+ meta_window_resize (window,
+ window->rect.width, window->rect.height);
+
+ /* move to top left corner */
+ x = window->screen->active_workspace->workarea.x;
+ y = window->screen->active_workspace->workarea.y;
+ if (window->frame)
+ {
+ x += window->frame->child_x;
+ y += window->frame->child_y;
+ }
+
+ meta_window_move (window, x, y);
+ }
+}
+
+void
+meta_window_unmaximize (MetaWindow *window)
+{
+ if (window->maximized)
+ {
+ int x, y;
+
+ window->maximized = FALSE;
+
+ meta_window_resize (window,
+ window->saved_rect.width,
+ window->saved_rect.height);
+
+ meta_window_move (window,
+ window->saved_rect.x,
+ window->saved_rect.y);
}
}
@@ -375,7 +434,10 @@ meta_window_move (MetaWindow *window,
{
window->frame->rect.x = new_x;
window->frame->rect.y = new_y;
-
+ /* window->rect.x, window->rect.y remain relative to frame,
+ * remember they are the server coords
+ */
+
XMoveWindow (window->display->xdisplay,
window->frame->xwindow,
window->frame->rect.x,
@@ -1003,17 +1065,48 @@ constrain_size (MetaWindow *window,
*/
int delta;
double min_aspect, max_aspect;
+ int minw, minh, maxw, maxh, fullw, fullh;
#define FLOOR(value, base) ( ((gint) ((value) / (base))) * (base) )
+
+ /* Get the allowed size ranges, considering maximized, etc. */
+ fullw = window->screen->active_workspace->workarea.width;
+ fullh = window->screen->active_workspace->workarea.height;
+ if (window->frame)
+ {
+ fullw -= window->frame->child_x + window->frame->right_width;
+ fullh -= window->frame->child_y + window->frame->bottom_height;
+ }
+
+ maxw = window->size_hints.max_width;
+ maxh = window->size_hints.max_height;
+ if (window->maximized)
+ {
+ maxw = MIN (maxw, fullw);
+ maxh = MIN (maxh, fullh);
+ }
+
+ minw = window->size_hints.min_width;
+ minh = window->size_hints.min_height;
+ if (window->maximized)
+ {
+ minw = MAX (minw, fullw);
+ minh = MAX (minh, fullh);
+ }
+
+ /* Check that fullscreen doesn't exceed max width hint,
+ * if so then snap back to max width hint
+ */
+ if (minw > maxw)
+ minw = maxw;
+ if (minh > maxh)
+ minh = maxh;
/* clamp width and height to min and max values
*/
- width = CLAMP (width,
- window->size_hints.min_width,
- window->size_hints.max_width);
- height = CLAMP (height,
- window->size_hints.min_height,
- window->size_hints.max_height);
+ width = CLAMP (width, minw, maxw);
+
+ height = CLAMP (height, minh, maxh);
/* shrink to base + N * inc
*/
diff --git a/src/window.h b/src/window.h
index 70c2a11a..38d4440a 100644
--- a/src/window.h
+++ b/src/window.h
@@ -39,12 +39,14 @@ struct _MetaWindow
char *desc; /* used in debug spew */
char *title;
+ /* Whether we're maximized */
+ guint maximized : 1;
/* Mapped is what we think the mapped state should be;
* so if we get UnmapNotify and mapped == TRUE then
* it's a withdraw, if mapped == FALSE the UnmapNotify
* is caused by us.
*/
- guint mapped : 1;
+ guint mapped : 1 ;
/* Minimize is the state controlled by the minimize button */
guint minimized : 1;
/* Iconic is the state in WM_STATE; happens for workspaces/shading
@@ -67,8 +69,19 @@ struct _MetaWindow
*/
guint has_focus : 1;
- /* The size we set the window to last. */
+ /* The size we set the window to last (i.e. what we believe
+ * to be its actual size on the server). The x, y are
+ * the actual server-side x,y so are relative to the frame
+ * or the root window as appropriate.
+ */
MetaRectangle rect;
+
+ /* The geometry to restore when we unmaximize.
+ * The position is in root window coords, even if
+ * there's a frame, which contrasts with window->rect
+ * above.
+ */
+ MetaRectangle saved_rect;
/* Requested geometry */
int border_width;
@@ -86,6 +99,8 @@ void meta_window_unminimize (MetaWindow *window);
void meta_window_resize (MetaWindow *window,
int w,
int h);
+void meta_window_maximize (MetaWindow *window);
+void meta_window_unmaximize (MetaWindow *window);
/* args to move are window pos, not frame pos */
void meta_window_move (MetaWindow *window,
diff --git a/src/workspace.c b/src/workspace.c
index d0e2339f..2e1fb53d 100644
--- a/src/workspace.c
+++ b/src/workspace.c
@@ -34,6 +34,14 @@ meta_workspace_new (MetaScreen *screen)
workspace->screen->display->workspaces =
g_list_append (workspace->screen->display->workspaces, workspace);
workspace->windows = NULL;
+
+ /* This may have something to do with the strut hints
+ * eventually
+ */
+ workspace->workarea.x = 0;
+ workspace->workarea.y = 0;
+ workspace->workarea.width = WidthOfScreen (screen->xscreen);
+ workspace->workarea.height = HeightOfScreen (screen->xscreen);
return workspace;
}
diff --git a/src/workspace.h b/src/workspace.h
index dcf808d5..5cde8a0a 100644
--- a/src/workspace.h
+++ b/src/workspace.h
@@ -29,6 +29,8 @@ struct _MetaWorkspace
MetaScreen *screen;
GList *windows;
+
+ MetaRectangle workarea;
};
MetaWorkspace* meta_workspace_new (MetaScreen *screen);