summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHavoc Pennington <hp@pobox.com>2001-08-30 04:01:38 +0000
committerHavoc Pennington <hp@src.gnome.org>2001-08-30 04:01:38 +0000
commit3e1c68b88a5e4d0fd688929fafe280efe73734f8 (patch)
tree396fd512ff3ceb5a0e712dc3c6d9519dc9a7633d
parent6d31d4756e219696b9ae7cdee986eca452883005 (diff)
downloadmetacity-3e1c68b88a5e4d0fd688929fafe280efe73734f8.tar.gz
avoid focusing a window on tab popup popdown
2001-08-29 Havoc Pennington <hp@pobox.com> * src/display.c (event_callback): avoid focusing a window on tab popup popdown * src/screen.c (meta_screen_ensure_tab_popup): compute frame outline size here
-rw-r--r--ChangeLog8
-rw-r--r--src/core.c29
-rw-r--r--src/core.h10
-rw-r--r--src/display.c26
-rw-r--r--src/display.h4
-rw-r--r--src/place.c6
-rw-r--r--src/screen.c27
-rw-r--r--src/tabpopup.c137
-rw-r--r--src/tabpopup.h55
-rw-r--r--src/ui.c24
-rw-r--r--src/ui.h24
11 files changed, 236 insertions, 114 deletions
diff --git a/ChangeLog b/ChangeLog
index 3f1a1e8c..bc8bf05b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2001-08-29 Havoc Pennington <hp@pobox.com>
+
+ * src/display.c (event_callback): avoid focusing a window on tab
+ popup popdown
+
+ * src/screen.c (meta_screen_ensure_tab_popup): compute frame
+ outline size here
+
2001-08-29 Havoc Pennington <hp@redhat.com>
* src/tabpopup.c: Switch back to outline.
diff --git a/src/core.c b/src/core.c
index 622397cf..ae36b4bc 100644
--- a/src/core.c
+++ b/src/core.c
@@ -24,24 +24,6 @@
#include "workspace.h"
void
-meta_core_get_outer_rect (Display *xdisplay,
- Window frame_xwindow,
- GdkRectangle *rect)
-{
- MetaDisplay *display;
- MetaWindow *window;
- MetaRectangle r;
-
- display = meta_display_for_x_display (xdisplay);
- window = meta_display_lookup_x_window (display, frame_xwindow);
-
- if (window == NULL || window->frame == NULL)
- meta_bug ("No such frame window 0x%lx!\n", frame_xwindow);
-
-
-}
-
-void
meta_core_get_frame_size (Display *xdisplay,
Window frame_xwindow,
int *width,
@@ -510,3 +492,14 @@ meta_core_set_screen_cursor (Display *xdisplay,
meta_screen_set_cursor (window->screen, cursor);
}
+
+void
+meta_core_increment_event_serial (Display *xdisplay)
+{
+ MetaDisplay *display;
+
+ display = meta_display_for_x_display (xdisplay);
+
+ meta_display_increment_event_serial (display);
+}
+
diff --git a/src/core.h b/src/core.h
index 766bbb04..24b2c633 100644
--- a/src/core.h
+++ b/src/core.h
@@ -28,10 +28,6 @@
#include "frames.h"
#include "common.h"
-void meta_core_get_outer_rect (Display *xdisplay,
- Window frame_xwindow,
- GdkRectangle *rect);
-
void meta_core_get_frame_size (Display *xdisplay,
Window frame_xwindow,
int *width,
@@ -128,6 +124,12 @@ void meta_core_set_screen_cursor (Display *xdisplay,
Window frame_on_screen,
MetaCursor cursor);
+/* Used because we ignore EnterNotify when a window is unmapped that
+ * really shouldn't cause focus changes, by comparing the event serial
+ * of the EnterNotify and the UnmapNotify.
+ */
+void meta_core_increment_event_serial (Display *display);
+
#endif
diff --git a/src/display.c b/src/display.c
index f709f419..2a17d41e 100644
--- a/src/display.c
+++ b/src/display.c
@@ -288,6 +288,8 @@ meta_display_open (const char *name)
display->last_button_num = 0;
display->is_double_click = FALSE;
+ display->last_ignored_unmap_serial = 0;
+
display->grab_op = META_GRAB_OP_NONE;
display->grab_window = NULL;
@@ -644,6 +646,16 @@ event_callback (XEvent *event,
display->last_button_xwindow = event->xbutton.window;
display->last_button_time = event->xbutton.time;
}
+ else if (event->type == UnmapNotify)
+ {
+ if (meta_ui_window_should_not_cause_focus (display->xdisplay,
+ event->xunmap.window))
+ {
+ display->last_ignored_unmap_serial = event->xany.serial;
+ meta_verbose ("Will not focus on EnterNotify with serial %lu\n",
+ display->last_ignored_unmap_serial);
+ }
+ }
modified = event_get_modified_window (display, event);
@@ -728,7 +740,7 @@ event_callback (XEvent *event,
break;
case EnterNotify:
/* do this even if window->has_focus to avoid races */
- if (window)
+ if (window && event->xany.serial != display->last_ignored_unmap_serial)
meta_window_focus (window, event->xcrossing.time);
break;
case LeaveNotify:
@@ -1263,8 +1275,9 @@ meta_spew_event (MetaDisplay *display,
else
winname = g_strdup_printf ("0x%lx", event->xany.window);
- meta_verbose ("%s on %s%s %s\n", name, winname,
- extra ? ":" : "", extra ? extra : "");
+ meta_verbose ("%s on %s%s %s serial %lu\n", name, winname,
+ extra ? ":" : "", extra ? extra : "",
+ event->xany.serial);
g_free (winname);
@@ -1645,3 +1658,10 @@ meta_display_ungrab_window_buttons (MetaDisplay *display,
}
}
+void
+meta_display_increment_event_serial (MetaDisplay *display)
+{
+ /* We just make some random X request */
+ XDeleteProperty (display->xdisplay, display->leader_window,
+ display->atom_motif_wm_hints);
+}
diff --git a/src/display.h b/src/display.h
index a94aa8f5..b2552dab 100644
--- a/src/display.h
+++ b/src/display.h
@@ -124,6 +124,8 @@ struct _MetaDisplay
Window last_button_xwindow;
int last_button_num;
guint is_double_click : 1;
+
+ unsigned long last_ignored_unmap_serial;
/* current window operation */
MetaGrabOp grab_op;
@@ -189,5 +191,7 @@ void meta_display_grab_window_buttons (MetaDisplay *display,
void meta_display_ungrab_window_buttons (MetaDisplay *display,
Window xwindow);
+/* make a request to ensure the event serial has changed */
+void meta_display_increment_event_serial (MetaDisplay *display);
#endif
diff --git a/src/place.c b/src/place.c
index 1e091f4d..0226af41 100644
--- a/src/place.c
+++ b/src/place.c
@@ -220,7 +220,11 @@ meta_window_place (MetaWindow *window,
*/
meta_verbose ("Placing window %s\n", window->desc);
-
+
+ /* FIXME copying Mac, when placing a dialog
+ * put it at 1/5 down and horizontally centered
+ */
+
if (window->xtransient_for != None)
{
/* Center horizontally, at top of parent vertically */
diff --git a/src/screen.c b/src/screen.c
index 22ab84e4..cb486f23 100644
--- a/src/screen.c
+++ b/src/screen.c
@@ -491,6 +491,33 @@ meta_screen_ensure_tab_popup (MetaScreen *screen)
entries[i].y = r.y;
entries[i].width = r.width;
entries[i].height = r.height;
+
+ /* Find inside of highlight rectangle to be used
+ * when window is outlined for tabbing.
+ * This should be the size of the east/west frame,
+ * and the size of the south frame, on those sides.
+ * on the top it should be the size of the south frame
+ * edge.
+ */
+ if (window->frame)
+ {
+ int south = window->frame->rect.height - window->frame->child_y -
+ window->rect.height;
+ int east = window->frame->child_x;
+ entries[i].inner_x = east;
+ entries[i].inner_y = south;
+ entries[i].inner_width = window->rect.width;
+ entries[i].inner_height = window->frame->rect.height - south * 2;
+ }
+ else
+ {
+ /* Use an arbitrary border size */
+#define OUTLINE_WIDTH 5
+ entries[i].inner_x = OUTLINE_WIDTH;
+ entries[i].inner_y = OUTLINE_WIDTH;
+ entries[i].inner_width = window->rect.width - OUTLINE_WIDTH * 2;
+ entries[i].inner_height = window->rect.height - OUTLINE_WIDTH * 2;
+ }
++i;
tmp = tmp->next;
diff --git a/src/tabpopup.c b/src/tabpopup.c
index 34e325b0..47edfba9 100644
--- a/src/tabpopup.c
+++ b/src/tabpopup.c
@@ -19,14 +19,14 @@
* 02111-1307, USA.
*/
-#include "ui.h"
#include "util.h"
+#include "core.h"
+#include "tabpopup.h"
#include <math.h>
#include <gtk/gtk.h>
#define OUTSIDE_SELECT_RECT 2
#define INSIDE_SELECT_RECT 2
-#define OUTLINE_WIDTH 5
typedef struct _TabEntry TabEntry;
@@ -37,6 +37,7 @@ struct _TabEntry
GdkPixbuf *icon;
GtkWidget *widget;
GdkRectangle rect;
+ GdkRectangle inner_rect;
};
struct _MetaTabPopup
@@ -60,35 +61,31 @@ outline_window_expose (GtkWidget *widget,
{
MetaTabPopup *popup;
int w, h;
- int icon_x, icon_y;
+ TabEntry *te;
popup = data;
if (popup->current_selected_entry == NULL)
return FALSE;
+
+ te = popup->current_selected_entry;
gdk_window_get_size (widget->window, &w, &h);
gdk_draw_rectangle (widget->window,
widget->style->white_gc,
- TRUE,
- OUTLINE_WIDTH, OUTLINE_WIDTH,
- w - OUTLINE_WIDTH * 2,
- h - OUTLINE_WIDTH * 2);
-
- icon_x = (w - gdk_pixbuf_get_width (popup->current_selected_entry->icon)) / 2;
- icon_y = (h - gdk_pixbuf_get_height (popup->current_selected_entry->icon)) / 2;
-
- gdk_pixbuf_render_to_drawable_alpha (popup->current_selected_entry->icon,
- widget->window,
- 0, 0, icon_x, icon_y,
- gdk_pixbuf_get_width (popup->current_selected_entry->icon),
- gdk_pixbuf_get_height (popup->current_selected_entry->icon),
- GDK_PIXBUF_ALPHA_FULL,
- 128,
- GDK_RGB_DITHER_NORMAL,
- 0, 0);
+ FALSE,
+ 0, 0,
+ te->rect.width - 1,
+ te->rect.height - 1);
+ gdk_draw_rectangle (widget->window,
+ widget->style->white_gc,
+ FALSE,
+ te->inner_rect.x - 1, te->inner_rect.y - 1,
+ te->inner_rect.width + 1,
+ te->inner_rect.height + 1);
+
return FALSE;
}
@@ -101,6 +98,8 @@ meta_ui_tab_popup_new (const MetaTabEntry *entries)
int width;
int height;
GtkWidget *table;
+ GtkWidget *vbox;
+ GtkWidget *align;
GList *tmp;
GtkWidget *frame;
int max_label_width;
@@ -110,10 +109,9 @@ meta_ui_tab_popup_new (const MetaTabEntry *entries)
popup->outline_window = gtk_window_new (GTK_WINDOW_POPUP);
gtk_widget_set_app_paintable (popup->outline_window, TRUE);
gtk_widget_realize (popup->outline_window);
-#if 0
+
g_signal_connect (G_OBJECT (popup->outline_window), "expose_event",
G_CALLBACK (outline_window_expose), popup);
-#endif
popup->window = gtk_window_new (GTK_WINDOW_POPUP);
gtk_window_set_position (GTK_WINDOW (popup->window),
@@ -142,6 +140,11 @@ meta_ui_tab_popup_new (const MetaTabEntry *entries)
te->rect.y = entries[i].y;
te->rect.width = entries[i].width;
te->rect.height = entries[i].height;
+
+ te->inner_rect.x = entries[i].inner_x;
+ te->inner_rect.y = entries[i].inner_y;
+ te->inner_rect.width = entries[i].inner_width;
+ te->inner_rect.height = entries[i].inner_height;
tab_entries = g_list_prepend (tab_entries, te);
@@ -155,7 +158,8 @@ meta_ui_tab_popup_new (const MetaTabEntry *entries)
if (i % width)
height += 1;
- table = gtk_table_new (height + 1, width, FALSE);
+ table = gtk_table_new (height, width, FALSE);
+ vbox = gtk_vbox_new (FALSE, 0);
frame = gtk_frame_new (NULL);
gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT);
@@ -163,17 +167,19 @@ meta_ui_tab_popup_new (const MetaTabEntry *entries)
gtk_container_add (GTK_CONTAINER (popup->window),
frame);
gtk_container_add (GTK_CONTAINER (frame),
- table);
+ vbox);
+ align = gtk_alignment_new (0.5, 0.5, 1.0, 1.0);
- popup->label = gtk_label_new ("");
-
- gtk_table_attach (GTK_TABLE (table),
- popup->label,
- 0, width, height, height + 1,
- GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
- 3, 3);
+ gtk_box_pack_start (GTK_BOX (vbox), align, TRUE, TRUE, 0);
+
+ gtk_container_add (GTK_CONTAINER (align),
+ table);
+ popup->label = gtk_label_new ("");
+ gtk_misc_set_padding (GTK_MISC (popup->label), 3, 3);
+
+ gtk_box_pack_end (GTK_BOX (vbox), popup->label, FALSE, FALSE, 0);
max_label_width = 0;
top = 0;
@@ -205,7 +211,7 @@ meta_ui_tab_popup_new (const MetaTabEntry *entries)
gtk_table_attach (GTK_TABLE (table),
te->widget,
left, right, top, bottom,
- GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
+ 0, 0,
0, 0);
/* Efficiency rules! */
@@ -227,8 +233,10 @@ meta_ui_tab_popup_new (const MetaTabEntry *entries)
/* remove all the temporary text */
gtk_label_set_text (GTK_LABEL (popup->label), "");
+ max_label_width += 20; /* add random padding */
+
gtk_window_set_default_size (GTK_WINDOW (popup->window),
- max_label_width + 20 /* random number */,
+ max_label_width,
-1);
return popup;
@@ -267,15 +275,20 @@ meta_ui_tab_popup_set_showing (MetaTabPopup *popup,
if (showing)
gtk_widget_show_all (popup->window);
else
- gtk_widget_hide (popup->window);
+ {
+ gtk_widget_hide (popup->window);
+ meta_core_increment_event_serial (gdk_display);
+ }
}
static void
display_entry (MetaTabPopup *popup,
TabEntry *te)
{
- GdkRectangle inner;
GdkRectangle rect;
+ GdkRegion *region;
+ GdkRegion *inner_region;
+
if (popup->current_selected_entry)
unselect_image (popup->current_selected_entry->widget);
@@ -285,42 +298,34 @@ display_entry (MetaTabPopup *popup,
/* Do stuff behind gtk's back */
gdk_window_hide (popup->outline_window->window);
-
+ meta_core_increment_event_serial (gdk_display);
+
rect = te->rect;
rect.x = 0;
rect.y = 0;
+
+ gdk_window_move_resize (popup->outline_window->window,
+ te->rect.x, te->rect.y,
+ te->rect.width, te->rect.height);
- inner = rect;
- inner.x += OUTLINE_WIDTH;
- inner.y += OUTLINE_WIDTH;
- inner.width -= OUTLINE_WIDTH * 2;
- inner.height -= OUTLINE_WIDTH * 2;
- if (inner.width >= 0 || inner.height >= 0)
- {
- GdkRegion *region;
- GdkRegion *inner_region;
+ gdk_window_set_background (popup->outline_window->window,
+ &popup->outline_window->style->black);
+
+ region = gdk_region_rectangle (&rect);
+ inner_region = gdk_region_rectangle (&te->inner_rect);
+ gdk_region_subtract (region, inner_region);
+ gdk_region_destroy (inner_region);
+
+ gdk_window_shape_combine_region (popup->outline_window->window,
+ region,
+ 0, 0);
- gdk_window_move_resize (popup->outline_window->window,
- te->rect.x, te->rect.y,
- te->rect.width, te->rect.height);
-
- gdk_window_set_background (popup->outline_window->window,
- &popup->outline_window->style->black);
-
- region = gdk_region_rectangle (&rect);
- inner_region = gdk_region_rectangle (&inner);
- gdk_region_subtract (region, inner_region);
- gdk_region_destroy (inner_region);
-
- gdk_window_shape_combine_region (popup->outline_window->window,
- region,
- 0, 0);
-
- /* This should piss off gtk a bit, but we don't want to raise
- * above the tab popup
- */
- gdk_window_show_unraised (popup->outline_window->window);
- }
+ gdk_region_destroy (region);
+
+ /* This should piss off gtk a bit, but we don't want to raise
+ * above the tab popup
+ */
+ gdk_window_show_unraised (popup->outline_window->window);
/* Must be before we handle an expose for the outline window */
popup->current_selected_entry = te;
diff --git a/src/tabpopup.h b/src/tabpopup.h
new file mode 100644
index 00000000..f861f02f
--- /dev/null
+++ b/src/tabpopup.h
@@ -0,0 +1,55 @@
+/* Metacity tab popup window */
+
+/*
+ * 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_TABPOPUP_H
+#define META_TABPOPUP_H
+
+/* Don't include gtk.h or gdk.h here */
+#include "common.h"
+#include <X11/Xlib.h>
+#include <glib.h>
+#include <gdk-pixbuf/gdk-pixbuf.h>
+
+typedef struct _MetaTabEntry MetaTabEntry;
+typedef struct _MetaTabPopup MetaTabPopup;
+
+struct _MetaTabEntry
+{
+ Window xwindow;
+ const char *title;
+ GdkPixbuf *icon;
+ int x, y, width, height;
+ int inner_x, inner_y, inner_width, inner_height;
+};
+
+MetaTabPopup* meta_ui_tab_popup_new (const MetaTabEntry *entries);
+void meta_ui_tab_popup_free (MetaTabPopup *popup);
+void meta_ui_tab_popup_set_showing (MetaTabPopup *popup,
+ gboolean showing);
+void meta_ui_tab_popup_forward (MetaTabPopup *popup);
+void meta_ui_tab_popup_backward (MetaTabPopup *popup);
+Window meta_ui_tab_popup_get_selected (MetaTabPopup *popup);
+void meta_ui_tab_popup_select (MetaTabPopup *popup,
+ Window xwindow);
+
+
+#endif
+
diff --git a/src/ui.c b/src/ui.c
index ff9d1ba8..7dd50e80 100644
--- a/src/ui.c
+++ b/src/ui.c
@@ -171,7 +171,7 @@ meta_ui_unmap_frame (MetaUI *ui,
window = gdk_xid_table_lookup (xwindow);
- if (window)
+ if (window)
gdk_window_hide (window);
}
@@ -270,7 +270,10 @@ meta_image_window_set_showing (MetaImageWindow *iw,
if (showing)
gtk_widget_show_all (iw->window);
else
- gtk_widget_hide (iw->window);
+ {
+ gtk_widget_hide (iw->window);
+ meta_core_increment_event_serial (gdk_display);
+ }
}
void
@@ -424,3 +427,20 @@ meta_ui_get_default_window_icon (MetaUI *ui)
GTK_ICON_SIZE_LARGE_TOOLBAR,
NULL);
}
+
+gboolean
+meta_ui_window_should_not_cause_focus (Display *xdisplay,
+ Window xwindow)
+{
+ GdkWindow *window;
+
+ window = gdk_xid_table_lookup (xwindow);
+
+ /* we shouldn't cause focus if we're an override redirect
+ * toplevel which is not foreign
+ */
+ if (window && gdk_window_get_type (window) == GDK_WINDOW_TEMP)
+ return TRUE;
+ else
+ return FALSE;
+}
diff --git a/src/ui.h b/src/ui.h
index 6f6adbfa..11417c0e 100644
--- a/src/ui.h
+++ b/src/ui.h
@@ -101,6 +101,7 @@ void meta_image_window_set_position (MetaImageWindow *iw,
int x,
int y);
+/* FIXME these lack a display arg */
GdkPixbuf* meta_gdk_pixbuf_get_from_window (GdkPixbuf *dest,
Window xwindow,
int src_x,
@@ -128,27 +129,10 @@ void meta_ui_pop_delay_exposes (MetaUI *ui);
GdkPixbuf* meta_ui_get_default_window_icon (MetaUI *ui);
-typedef struct _MetaTabEntry MetaTabEntry;
-typedef struct _MetaTabPopup MetaTabPopup;
-
-struct _MetaTabEntry
-{
- Window xwindow;
- const char *title;
- GdkPixbuf *icon;
- int x, y, width, height;
-};
-
-MetaTabPopup* meta_ui_tab_popup_new (const MetaTabEntry *entries);
-void meta_ui_tab_popup_free (MetaTabPopup *popup);
-void meta_ui_tab_popup_set_showing (MetaTabPopup *popup,
- gboolean showing);
-void meta_ui_tab_popup_forward (MetaTabPopup *popup);
-void meta_ui_tab_popup_backward (MetaTabPopup *popup);
-Window meta_ui_tab_popup_get_selected (MetaTabPopup *popup);
-void meta_ui_tab_popup_select (MetaTabPopup *popup,
- Window xwindow);
+gboolean meta_ui_window_should_not_cause_focus (Display *xdisplay,
+ Window xwindow);
+#include "tabpopup.h"
#endif