...
This commit is contained in:
parent
834452ca2c
commit
0feac37c5b
11 changed files with 276 additions and 22 deletions
|
@ -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:
|
||||
{
|
||||
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";
|
||||
|
|
|
@ -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
|
||||
|
|
27
src/frame.c
27
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;
|
||||
|
|
|
@ -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;
|
||||
|
|
43
src/menu.c
43
src/menu.c
|
@ -175,6 +175,27 @@ meta_window_menu_hide (void)
|
|||
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
|
||||
activate_cb (GtkWidget *menuitem, gpointer data)
|
||||
{
|
||||
|
@ -182,8 +203,28 @@ activate_cb (GtkWidget *menuitem, gpointer data)
|
|||
|
||||
md = data;
|
||||
|
||||
meta_ui_warning ("Activated menuitem\n");
|
||||
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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -175,6 +175,27 @@ meta_window_menu_hide (void)
|
|||
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
|
||||
activate_cb (GtkWidget *menuitem, gpointer data)
|
||||
{
|
||||
|
@ -182,8 +203,28 @@ activate_cb (GtkWidget *menuitem, gpointer data)
|
|||
|
||||
md = data;
|
||||
|
||||
meta_ui_warning ("Activated menuitem\n");
|
||||
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);
|
||||
|
|
109
src/window.c
109
src/window.c
|
@ -129,6 +129,9 @@ meta_window_new (MetaDisplay *display, Window xwindow)
|
|||
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;
|
||||
|
@ -199,6 +203,8 @@ meta_window_free (MetaWindow *window)
|
|||
|
||||
g_assert (window->workspaces == NULL);
|
||||
|
||||
/* FIXME restore original size if window has maximized */
|
||||
|
||||
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,6 +434,9 @@ 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,
|
||||
|
@ -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
|
||||
*/
|
||||
|
|
17
src/window.h
17
src/window.h
|
@ -39,6 +39,8 @@ 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
|
||||
|
@ -67,9 +69,20 @@ 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;
|
||||
/* x/y/w/h here get filled with ConfigureRequest values */
|
||||
|
@ -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,
|
||||
|
|
|
@ -35,6 +35,14 @@ meta_workspace_new (MetaScreen *screen)
|
|||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -29,6 +29,8 @@ struct _MetaWorkspace
|
|||
MetaScreen *screen;
|
||||
|
||||
GList *windows;
|
||||
|
||||
MetaRectangle workarea;
|
||||
};
|
||||
|
||||
MetaWorkspace* meta_workspace_new (MetaScreen *screen);
|
||||
|
|
Loading…
Reference in a new issue