summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrhp <rhp>2001-06-04 06:17:52 +0000
committerrhp <rhp>2001-06-04 06:17:52 +0000
commitad6efc61b5d8c4572eac2ad586bca4e7b54d9c7c (patch)
tree02ed43632f8e5fac78be60d2a24d2daf421677a4
parent1cd2915ba3dc15278392c3f6b5579e6a43aca962 (diff)
downloadmetacity-ad6efc61b5d8c4572eac2ad586bca4e7b54d9c7c.tar.gz
...
-rw-r--r--src/display.c28
-rw-r--r--src/frame.c21
-rw-r--r--src/window.c92
-rw-r--r--src/window.h31
4 files changed, 153 insertions, 19 deletions
diff --git a/src/display.c b/src/display.c
index 6215be61..19e88e40 100644
--- a/src/display.c
+++ b/src/display.c
@@ -68,7 +68,15 @@ meta_display_open (const char *name)
GSList *screens;
GSList *tmp;
int i;
- char *atom_names[] = { "_NET_WM_NAME", "WM_PROTOCOLS", "WM_TAKE_FOCUS", "WM_DELETE_WINDOW" };
+ /* Remember to edit code that assigns each atom to display struct
+ * when adding an atom name here.
+ */
+ char *atom_names[] = {
+ "_NET_WM_NAME",
+ "WM_PROTOCOLS",
+ "WM_TAKE_FOCUS",
+ "WM_DELETE_WINDOW"
+ };
Atom atoms[G_N_ELEMENTS(atom_names)];
meta_verbose ("Opening display '%s'\n", XDisplayName (name));
@@ -136,6 +144,9 @@ meta_display_open (const char *name)
XInternAtoms (display->xdisplay, atom_names, G_N_ELEMENTS (atom_names),
False, atoms);
display->atom_net_wm_name = atoms[0];
+ display->atom_wm_protocols = atoms[1];
+ display->atom_wm_take_focus = atoms[2];
+ display->atom_wm_delete_window = atoms[3];
/* Now manage all existing windows */
tmp = display->screens;
@@ -184,6 +195,8 @@ meta_display_close (MetaDisplay *display)
winlist = g_slist_sort (winlist, ptrcmp);
+ /* Unmanage all windows */
+ meta_display_grab (display);
tmp = winlist;
while (tmp != NULL)
{
@@ -194,6 +207,7 @@ meta_display_close (MetaDisplay *display)
tmp = tmp->next;
}
g_slist_free (winlist);
+ meta_display_ungrab (display);
/* Must be after all calls to meta_window_free() since they
* unregister windows
@@ -397,10 +411,16 @@ event_queue_callback (MetaEventQueue *queue,
meta_window_free (window); /* Unmanage destroyed window */
break;
case UnmapNotify:
- if (window)
- meta_window_free (window); /* Unmanage withdrawn window */
+ if (window && window->mapped)
+ {
+ meta_verbose ("Window %s withdrawn\n",
+ window->desc);
+ meta_window_free (window); /* Unmanage withdrawn window */
+ }
break;
case MapNotify:
+ if (window)
+ window->mapped = TRUE;
break;
case MapRequest:
if (window == NULL)
@@ -414,6 +434,8 @@ event_queue_callback (MetaEventQueue *queue,
/* Unmanage it, override_redirect was toggled on?
* Can this happen?
*/
+ meta_verbose ("Window %s toggled on override redirect\n",
+ window->desc);
meta_window_free (window);
}
break;
diff --git a/src/frame.c b/src/frame.c
index 20e9202a..92da35fa 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -29,7 +29,7 @@ meta_frame_init_info (MetaFrame *frame,
MetaFrameInfo *info)
{
info->flags =
- META_FRAME_ALLOWS_DELETE | META_FRAME_ALLOWS_MENU |
+ META_FRAME_ALLOWS_MENU | META_FRAME_ALLOWS_DELETE |
META_FRAME_ALLOWS_ICONIFY | META_FRAME_ALLOWS_MAXIMIZE |
META_FRAME_ALLOWS_RESIZE;
@@ -198,9 +198,6 @@ meta_window_ensure_frame (MetaWindow *window)
if (window->frame)
return;
-
- /* Need to fix Pango, it grabs the server */
- g_return_if_fail (window->display->server_grab_count == 0);
frame = g_new (MetaFrame, 1);
@@ -262,6 +259,9 @@ meta_window_ensure_frame (MetaWindow *window)
meta_display_grab (window->display);
meta_error_trap_push (window->display);
+ window->mapped = FALSE; /* the reparent will unmap the window,
+ * we don't want to take that as a withdraw
+ */
XReparentWindow (window->display->xdisplay,
window->xwindow,
frame->xwindow,
@@ -274,8 +274,9 @@ meta_window_ensure_frame (MetaWindow *window)
window->rect.y = frame->child_y;
/* stick frame to the window */
- window->frame = frame;
+ window->frame = frame;
+ /* Put our state back where it should be */
if (window->iconic)
meta_window_hide (window);
else
@@ -306,6 +307,10 @@ meta_window_destroy_frame (MetaWindow *window)
* thus the error trap.
*/
meta_error_trap_push (window->display);
+ window->mapped = FALSE; /* Keep track of unmapping it, so we
+ * can identify a withdraw initiated
+ * by the client.
+ */
XReparentWindow (window->display->xdisplay,
window->xwindow,
window->screen->xroot,
@@ -323,6 +328,12 @@ meta_window_destroy_frame (MetaWindow *window)
XDestroyWindow (window->display->xdisplay, frame->xwindow);
g_free (frame);
+
+ /* Put our state back where it should be */
+ if (window->iconic)
+ meta_window_hide (window);
+ else
+ meta_window_show (window);
}
void
diff --git a/src/window.c b/src/window.c
index c4ad7f0c..32037f8f 100644
--- a/src/window.c
+++ b/src/window.c
@@ -121,12 +121,16 @@ meta_window_new (MetaDisplay *display, Window xwindow)
window->xvisual = attrs.visual;
window->title = NULL;
- window->iconic = FALSE;
window->desc = g_strdup_printf ("0x%lx", window->xwindow);
window->frame = NULL;
window->has_focus = FALSE;
+
+ window->initially_iconic = FALSE;
+ window->minimized = FALSE;
+ window->iconic = FALSE;
+ window->mapped = FALSE;
meta_display_register_x_window (display, &window->xwindow, window);
@@ -134,10 +138,24 @@ meta_window_new (MetaDisplay *display, Window xwindow)
update_title (window);
update_protocols (window);
update_wm_hints (window);
+
+ if (window->initially_iconic)
+ {
+ /* WM_HINTS said iconic */
+ window->iconic = TRUE;
+ }
meta_window_resize (window, window->size_hints.width, window->size_hints.height);
meta_window_ensure_frame (window);
+
+ /* Put our state where it should be (ensure_frame also did this
+ * for decorated windows, but should be harmless to do twice)
+ */
+ if (window->iconic)
+ meta_window_hide (window);
+ else
+ meta_window_show (window);
return window;
}
@@ -150,6 +168,15 @@ meta_window_free (MetaWindow *window)
meta_display_unregister_x_window (window->display, window->xwindow);
meta_window_destroy_frame (window);
+
+ /* Put back anything we messed up */
+ meta_error_trap_push (window->display);
+ if (window->border_width != 0)
+ XSetWindowBorderWidth (window->display->xdisplay,
+ window->xwindow,
+ window->border_width);
+
+ meta_error_trap_pop (window->display);
g_free (window->title);
g_free (window->desc);
@@ -163,7 +190,15 @@ meta_window_show (MetaWindow *window)
XMapWindow (window->display->xdisplay, window->frame->xwindow);
XMapWindow (window->display->xdisplay, window->xwindow);
+ /* These flags aren't always in sync, iconic
+ * is set only here in show/hide, mapped
+ * can be set in a couple other places where
+ * we map/unmap
+ */
+ window->mapped = TRUE;
window->iconic = FALSE;
+
+ /* FIXME update WM_STATE */
}
void
@@ -173,7 +208,30 @@ meta_window_hide (MetaWindow *window)
XUnmapWindow (window->display->xdisplay, window->frame->xwindow);
XUnmapWindow (window->display->xdisplay, window->xwindow);
+ window->mapped = FALSE;
window->iconic = TRUE;
+
+ /* FIXME update WM_STATE */
+}
+
+void
+meta_window_minimize (MetaWindow *window)
+{
+ if (!window->minimized)
+ {
+ window->minimized = TRUE;
+ meta_window_hide (window);
+ }
+}
+
+void
+meta_window_unminimize (MetaWindow *window)
+{
+ if (window->minimized)
+ {
+ window->minimized = FALSE;
+ meta_window_show (window);
+ }
}
void
@@ -206,9 +264,20 @@ meta_window_delete (MetaWindow *window,
Time timestamp)
{
meta_error_trap_push (window->display);
- meta_window_send_icccm_message (window,
- window->display->atom_wm_delete_window,
- timestamp);
+ if (window->delete_window)
+ {
+ meta_verbose ("Deleting %s with delete_window request\n",
+ window->desc);
+ meta_window_send_icccm_message (window,
+ window->display->atom_wm_delete_window,
+ timestamp);
+ }
+ else
+ {
+ meta_verbose ("Deleting %s with explicit kill\n",
+ window->desc);
+ XKillClient (window->display->xdisplay, window->xwindow);
+ }
meta_error_trap_pop (window->display);
}
@@ -322,6 +391,13 @@ process_property_notify (MetaWindow *window,
if (window->frame)
meta_frame_queue_recalc (window->frame);
}
+ else if (event->atom == XA_WM_HINTS)
+ {
+ update_wm_hints (window);
+
+ if (window->frame)
+ meta_frame_queue_recalc (window->frame);
+ }
return TRUE;
}
@@ -698,7 +774,7 @@ update_protocols (MetaWindow *window)
if (XGetWMProtocols (window->display->xdisplay,
window->xwindow,
&protocols,
- &n_protocols) == Success)
+ &n_protocols))
{
i = 0;
while (i < n_protocols)
@@ -727,6 +803,7 @@ update_wm_hints (MetaWindow *window)
/* Fill in defaults */
window->input = FALSE;
+ window->initially_iconic = FALSE;
meta_error_trap_push (window->display);
@@ -735,9 +812,14 @@ update_wm_hints (MetaWindow *window)
if (hints)
{
window->input = (hints->flags & InputHint) != 0;
+
+ window->initially_iconic = (hints->initial_state == IconicState);
/* FIXME there are a few others there. */
+ meta_verbose ("Read WM_HINTS input: %d iconic: %d\n",
+ window->input, window->initially_iconic);
+
XFree (hints);
}
diff --git a/src/window.h b/src/window.h
index 2d258cdf..453318dc 100644
--- a/src/window.h
+++ b/src/window.h
@@ -37,8 +37,25 @@ struct _MetaWindow
Visual *xvisual;
char *desc; /* used in debug spew */
char *title;
-
+
+ /* 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;
+ /* Minimize is the state controlled by the minimize button */
+ guint minimized : 1;
+ /* Iconic is the state in WM_STATE; happens for workspaces/shading
+ * in addition to minimize
+ */
guint iconic : 1;
+ /* initially_iconic is the WM_HINTS setting when we first manage
+ * the window.
+ */
+ guint initially_iconic : 1;
+
+ /* These are the two flags from WM_PROTOCOLS */
guint take_focus : 1;
guint delete_window : 1;
/* Globally active / No input */
@@ -58,11 +75,13 @@ struct _MetaWindow
XSizeHints size_hints;
};
-MetaWindow* meta_window_new (MetaDisplay *display,
- Window xwindow);
-void meta_window_free (MetaWindow *window);
-void meta_window_show (MetaWindow *window);
-void meta_window_hide (MetaWindow *window);
+MetaWindow* meta_window_new (MetaDisplay *display,
+ Window xwindow);
+void meta_window_free (MetaWindow *window);
+void meta_window_show (MetaWindow *window);
+void meta_window_hide (MetaWindow *window);
+void meta_window_minimize (MetaWindow *window);
+void meta_window_unminimize (MetaWindow *window);
void meta_window_resize (MetaWindow *window,
int w,
int h);