This commit is contained in:
rhp 2001-06-04 04:58:22 +00:00
parent c506b48624
commit 1cd2915ba3
8 changed files with 347 additions and 156 deletions

View File

@ -25,6 +25,7 @@
#include "screen.h" #include "screen.h"
#include "window.h" #include "window.h"
#include "frame.h" #include "frame.h"
#include "errors.h"
static GSList *all_displays = NULL; static GSList *all_displays = NULL;
static void meta_spew_event (MetaDisplay *display, static void meta_spew_event (MetaDisplay *display,
@ -180,26 +181,24 @@ meta_display_close (MetaDisplay *display)
g_hash_table_foreach (display->window_ids, g_hash_table_foreach (display->window_ids,
listify_func, listify_func,
&winlist); &winlist);
g_hash_table_destroy (display->window_ids);
winlist = g_slist_sort (winlist, ptrcmp); winlist = g_slist_sort (winlist, ptrcmp);
tmp = winlist; tmp = winlist;
while (tmp != NULL) while (tmp != NULL)
{ {
/* If the next node doesn't contain this window
* a second time, delete the window.
*/
g_assert (tmp->data != NULL);
if (tmp->next == NULL || if (tmp->next == NULL ||
(tmp->next && tmp->next->data != tmp->data)) (tmp->next && tmp->next->data != tmp->data))
meta_window_free (tmp->data); meta_window_free (tmp->data);
tmp = tmp->data; tmp = tmp->next;
} }
g_slist_free (winlist); g_slist_free (winlist);
/* Must be after all calls to meta_window_free() since they
* unregister windows
*/
g_hash_table_destroy (display->window_ids);
meta_event_queue_free (display->events); meta_event_queue_free (display->events);
XCloseDisplay (display->xdisplay); XCloseDisplay (display->xdisplay);
@ -352,12 +351,34 @@ event_queue_callback (MetaEventQueue *queue,
case MotionNotify: case MotionNotify:
break; break;
case EnterNotify: case EnterNotify:
/* We handle it here if an undecorated window
* is involved, otherwise we handle it in frame.c
*/
/* do this even if window->has_focus to avoid races */
if (window)
meta_window_focus (window, event->xcrossing.time);
break; break;
case LeaveNotify: case LeaveNotify:
break; break;
case FocusIn: case FocusIn:
if (window)
{
if (window != window->display->focus_window)
window->display->focus_window = window;
window->has_focus = TRUE;
if (window->frame)
meta_frame_queue_draw (window->frame);
}
break; break;
case FocusOut: case FocusOut:
if (window)
{
if (window == window->display->focus_window)
window->display->focus_window = NULL;
window->has_focus = FALSE;
if (window->frame)
meta_frame_queue_draw (window->frame);
}
break; break;
case KeymapNotify: case KeymapNotify:
break; break;
@ -470,8 +491,6 @@ event_get_modified_window (MetaDisplay *display,
case ButtonPress: case ButtonPress:
case ButtonRelease: case ButtonRelease:
case MotionNotify: case MotionNotify:
case EnterNotify:
case LeaveNotify:
case FocusIn: case FocusIn:
case FocusOut: case FocusOut:
case KeymapNotify: case KeymapNotify:
@ -486,8 +505,10 @@ event_get_modified_window (MetaDisplay *display,
case SelectionNotify: case SelectionNotify:
case ColormapNotify: case ColormapNotify:
case ClientMessage: case ClientMessage:
case EnterNotify:
case LeaveNotify:
return event->xany.window; return event->xany.window;
case CreateNotify: case CreateNotify:
return event->xcreatewindow.window; return event->xcreatewindow.window;
@ -558,9 +579,21 @@ meta_spew_event (MetaDisplay *display,
break; break;
case EnterNotify: case EnterNotify:
name = "EnterNotify"; name = "EnterNotify";
extra = g_strdup_printf ("win: 0x%lx root: 0x%lx subwindow: 0x%lx mode: %d detail: %d\n",
event->xcrossing.window,
event->xcrossing.root,
event->xcrossing.subwindow,
event->xcrossing.mode,
event->xcrossing.detail);
break; break;
case LeaveNotify: case LeaveNotify:
name = "LeaveNotify"; name = "LeaveNotify";
extra = g_strdup_printf ("win: 0x%lx root: 0x%lx subwindow: 0x%lx mode: %d detail: %d\n",
event->xcrossing.window,
event->xcrossing.root,
event->xcrossing.subwindow,
event->xcrossing.mode,
event->xcrossing.detail);
break; break;
case FocusIn: case FocusIn:
name = "FocusIn"; name = "FocusIn";

View File

@ -42,6 +42,11 @@ struct _MetaDisplay
Atom atom_wm_protocols; Atom atom_wm_protocols;
Atom atom_wm_take_focus; Atom atom_wm_take_focus;
Atom atom_wm_delete_window; Atom atom_wm_delete_window;
/* This is the actual window from focus events,
* not the one we last set
*/
MetaWindow *focus_window;
/*< private-ish >*/ /*< private-ish >*/
MetaEventQueue *events; MetaEventQueue *events;
@ -61,7 +66,6 @@ void meta_display_grab (MetaDisplay *display);
void meta_display_ungrab (MetaDisplay *display); void meta_display_ungrab (MetaDisplay *display);
PangoContext* meta_display_get_pango_context (MetaDisplay *display); PangoContext* meta_display_get_pango_context (MetaDisplay *display);
/* A given MetaWindow may have various X windows that "belong" /* A given MetaWindow may have various X windows that "belong"
* to it, such as the frame window. * to it, such as the frame window.
*/ */

View File

@ -32,6 +32,9 @@ meta_frame_init_info (MetaFrame *frame,
META_FRAME_ALLOWS_DELETE | META_FRAME_ALLOWS_MENU | META_FRAME_ALLOWS_DELETE | META_FRAME_ALLOWS_MENU |
META_FRAME_ALLOWS_ICONIFY | META_FRAME_ALLOWS_MAXIMIZE | META_FRAME_ALLOWS_ICONIFY | META_FRAME_ALLOWS_MAXIMIZE |
META_FRAME_ALLOWS_RESIZE; META_FRAME_ALLOWS_RESIZE;
if (frame->window->has_focus)
info->flags |= META_FRAME_HAS_FOCUS;
info->drawable = None; info->drawable = None;
info->xoffset = 0; info->xoffset = 0;
@ -142,6 +145,9 @@ meta_frame_calc_geometry (MetaFrame *frame,
frame->rect.width = frame->rect.width + geom.left_width + geom.right_width; frame->rect.width = frame->rect.width + geom.left_width + geom.right_width;
frame->rect.height = frame->rect.height + geom.top_height + geom.bottom_height; frame->rect.height = frame->rect.height + geom.top_height + geom.bottom_height;
meta_debug_spew ("Added top %d and bottom %d totalling %d over child height %d\n",
geom.top_height, geom.bottom_height, frame->rect.height, child_height);
frame->bg_pixel = geom.background_pixel; frame->bg_pixel = geom.background_pixel;
*geomp = geom; *geomp = geom;
@ -157,6 +163,18 @@ set_background_none (MetaFrame *frame)
frame->xwindow, frame->xwindow,
CWBackPixmap, CWBackPixmap,
&attrs); &attrs);
meta_debug_spew ("Frame size %d,%d %dx%d window size %d,%d %dx%d window pos %d,%d\n",
frame->rect.x,
frame->rect.y,
frame->rect.width,
frame->rect.height,
frame->window->rect.x,
frame->window->rect.y,
frame->window->rect.width,
frame->window->rect.height,
frame->child_x,
frame->child_y);
} }
static void static void
@ -211,8 +229,9 @@ meta_window_ensure_frame (MetaWindow *window)
attrs.background_pixel = frame->bg_pixel; attrs.background_pixel = frame->bg_pixel;
attrs.event_mask = attrs.event_mask =
StructureNotifyMask | SubstructureNotifyMask | ExposureMask | StructureNotifyMask | SubstructureNotifyMask | ExposureMask |
ButtonPressMask | ButtonReleaseMask | OwnerGrabButtonMask | ButtonPressMask | ButtonReleaseMask |
PointerMotionMask | PointerMotionHintMask; PointerMotionMask | PointerMotionHintMask |
EnterWindowMask | LeaveWindowMask;
frame->xwindow = XCreateWindow (window->display->xdisplay, frame->xwindow = XCreateWindow (window->display->xdisplay,
window->screen->xroot, window->screen->xroot,
@ -230,9 +249,6 @@ meta_window_ensure_frame (MetaWindow *window)
meta_verbose ("Frame is 0x%lx\n", frame->xwindow); meta_verbose ("Frame is 0x%lx\n", frame->xwindow);
frame->action = META_FRAME_ACTION_NONE; frame->action = META_FRAME_ACTION_NONE;
frame->last_x = 0;
frame->last_y = 0;
frame->start_button = 0;
meta_display_register_x_window (window->display, &frame->xwindow, window); meta_display_register_x_window (window->display, &frame->xwindow, window);
@ -502,31 +518,32 @@ static void
update_move (MetaFrame *frame) update_move (MetaFrame *frame)
{ {
int x, y; int x, y;
int new_x, new_y; int dx, dy;
frame_query_root_pointer (frame, &x, &y); frame_query_root_pointer (frame, &x, &y);
new_x = frame->rect.x + (x - frame->last_x); dx = x - frame->start_root_x;
new_y = frame->rect.y + (y - frame->last_y); dy = y - frame->start_root_y;
frame->last_x = x;
frame->last_y = y;
meta_frame_move (frame, new_x, new_y); meta_frame_move (frame,
frame->start_window_x + dx,
frame->start_window_y + dy);
} }
static void static void
update_resize_se (MetaFrame *frame) update_resize_se (MetaFrame *frame)
{ {
int x, y; int x, y;
int new_w, new_h; int dx, dy;
frame_query_root_pointer (frame, &x, &y); frame_query_root_pointer (frame, &x, &y);
new_w = frame->window->rect.width + (x - frame->last_x); dx = x - frame->start_root_x;
new_h = frame->window->rect.height + (y - frame->last_y); dy = y - frame->start_root_y;
frame->last_x = x;
frame->last_y = y;
meta_window_resize (frame->window, new_w, new_h); meta_window_resize (frame->window,
frame->start_window_x + dx,
frame->start_window_y + dy);
} }
gboolean gboolean
@ -555,8 +572,10 @@ meta_frame_event (MetaFrame *frame,
meta_verbose ("Begin move on %s\n", meta_verbose ("Begin move on %s\n",
frame->window->desc); frame->window->desc);
frame->action = META_FRAME_ACTION_MOVING; frame->action = META_FRAME_ACTION_MOVING;
frame->last_x = event->xbutton.x_root; frame->start_root_x = event->xbutton.x_root;
frame->last_y = event->xbutton.y_root; frame->start_root_y = event->xbutton.y_root;
frame->start_window_x = frame->rect.x;
frame->start_window_y = frame->rect.y;
frame->start_button = event->xbutton.button; frame->start_button = event->xbutton.button;
} }
else if (control == META_FRAME_CONTROL_DELETE && else if (control == META_FRAME_CONTROL_DELETE &&
@ -565,6 +584,7 @@ meta_frame_event (MetaFrame *frame,
/* FIXME delete event */ /* FIXME delete event */
meta_verbose ("Close control clicked on %s\n", meta_verbose ("Close control clicked on %s\n",
frame->window->desc); frame->window->desc);
meta_window_delete (frame->window, event->xbutton.time);
} }
else if (control == META_FRAME_CONTROL_RESIZE_SE && else if (control == META_FRAME_CONTROL_RESIZE_SE &&
event->xbutton.button == 1) event->xbutton.button == 1)
@ -572,8 +592,10 @@ meta_frame_event (MetaFrame *frame,
meta_verbose ("Resize control clicked on %s\n", meta_verbose ("Resize control clicked on %s\n",
frame->window->desc); frame->window->desc);
frame->action = META_FRAME_ACTION_RESIZING_SE; frame->action = META_FRAME_ACTION_RESIZING_SE;
frame->last_x = event->xbutton.x_root; frame->start_root_x = event->xbutton.x_root;
frame->last_y = event->xbutton.y_root; frame->start_root_y = event->xbutton.y_root;
frame->start_window_x = frame->window->rect.width;
frame->start_window_y = frame->window->rect.height;
frame->start_button = event->xbutton.button; frame->start_button = event->xbutton.button;
} }
} }
@ -622,6 +644,12 @@ meta_frame_event (MetaFrame *frame,
} }
break; break;
case EnterNotify: 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; break;
case LeaveNotify: case LeaveNotify:
break; break;

View File

@ -50,8 +50,11 @@ struct _MetaFrame
gulong bg_pixel; gulong bg_pixel;
MetaFrameAction action; MetaFrameAction action;
/* reference point for drags */ /* initial mouse position for drags */
int last_x, last_y; int start_root_x, start_root_y;
/* initial window size or initial window position for drags */
int start_window_x, start_window_y;
/* button doing the dragging */
int start_button; int start_button;
guint theme_acquired : 1; guint theme_acquired : 1;

View File

@ -10,5 +10,6 @@ elif test -z "$DEBUG"; then
fi fi
Xnest :1 -scrns $SCREENS -geometry 270x270 & Xnest :1 -scrns $SCREENS -geometry 270x270 &
DISPLAY=:1 xsetroot -solid royalblue3
METACITY_UISLAVE_DIR=./uislave DISPLAY=:1 unst libtool --mode=execute $DEBUG ./metacity METACITY_UISLAVE_DIR=./uislave DISPLAY=:1 unst libtool --mode=execute $DEBUG ./metacity
killall Xnest killall Xnest

View File

@ -55,6 +55,9 @@ struct _DefaultScreenData
GC fg_gc; GC fg_gc;
GC light_gc; GC light_gc;
GC dark_gc; GC dark_gc;
GC black_gc;
GC selected_gc;
GC selected_text_gc;
}; };
/* FIXME store this on the screen */ /* FIXME store this on the screen */
@ -69,13 +72,13 @@ default_acquire_frame (MetaFrameInfo *info)
if (screen_data == NULL) if (screen_data == NULL)
{ {
PangoColor color;
screen_data = g_new (DefaultScreenData, 1); screen_data = g_new (DefaultScreenData, 1);
vals.foreground = meta_get_x_pixel (info->screen, vals.foreground = meta_get_x_pixel (info->screen,
&info->colors->fg[META_STATE_NORMAL]); &info->colors->fg[META_STATE_NORMAL]);
/* FIXME memory-inefficient, could use the same one for all frames
* w/ the same root window
*/
screen_data->text_gc = XCreateGC (info->display, screen_data->text_gc = XCreateGC (info->display,
RootWindowOfScreen (info->screen), RootWindowOfScreen (info->screen),
GCForeground, GCForeground,
@ -98,6 +101,27 @@ default_acquire_frame (MetaFrameInfo *info)
RootWindowOfScreen (info->screen), RootWindowOfScreen (info->screen),
GCForeground, GCForeground,
&vals); &vals);
vals.foreground = meta_get_x_pixel (info->screen,
&info->colors->bg[META_STATE_SELECTED]);
screen_data->selected_gc = XCreateGC (info->display,
RootWindowOfScreen (info->screen),
GCForeground,
&vals);
vals.foreground = meta_get_x_pixel (info->screen,
&info->colors->fg[META_STATE_SELECTED]);
screen_data->selected_text_gc = XCreateGC (info->display,
RootWindowOfScreen (info->screen),
GCForeground,
&vals);
color.red = color.green = color.blue = 0;
vals.foreground = meta_get_x_pixel (info->screen,
&color);
screen_data->black_gc = XCreateGC (info->display,
RootWindowOfScreen (info->screen),
GCForeground,
&vals);
} }
d = g_new (DefaultFrameData, 1); d = g_new (DefaultFrameData, 1);
@ -126,13 +150,15 @@ default_release_frame (MetaFrameInfo *info,
g_free (d); g_free (d);
} }
#define VERTICAL_TITLE_PAD 2 #define ABOVE_TITLE_PAD 4
#define HORIZONTAL_TITLE_PAD 3 #define BELOW_TITLE_PAD 3
#define RIGHT_TITLE_PAD 4
#define LEFT_TITLE_PAD 3
#define VERTICAL_TEXT_PAD 2 #define VERTICAL_TEXT_PAD 2
#define HORIZONTAL_TEXT_PAD 2 #define HORIZONTAL_TEXT_PAD 2
#define LEFT_WIDTH 2 #define LEFT_WIDTH 6
#define RIGHT_WIDTH 2 #define RIGHT_WIDTH 6
#define BOTTOM_HEIGHT 5 #define BOTTOM_HEIGHT 7
#define SPACER_SPACING 3 #define SPACER_SPACING 3
#define SPACER_WIDTH 2 #define SPACER_WIDTH 2
#define SPACER_HEIGHT 10 #define SPACER_HEIGHT 10
@ -149,7 +175,7 @@ calc_geometry (MetaFrameInfo *info,
int button_y; int button_y;
int title_right_edge; int title_right_edge;
fgeom->top_height = MAX (d->layout_height + VERTICAL_TITLE_PAD * 2 + VERTICAL_TEXT_PAD * 2, fgeom->top_height = MAX (d->layout_height + VERTICAL_TEXT_PAD * 2 + ABOVE_TITLE_PAD + BELOW_TITLE_PAD,
BUTTON_HEIGHT + BUTTON_PAD * 2); BUTTON_HEIGHT + BUTTON_PAD * 2);
fgeom->left_width = LEFT_WIDTH; fgeom->left_width = LEFT_WIDTH;
@ -229,7 +255,7 @@ calc_geometry (MetaFrameInfo *info,
fgeom->spacer_rect.height = 0; fgeom->spacer_rect.height = 0;
} }
title_right_edge = x - HORIZONTAL_TITLE_PAD; title_right_edge = x - RIGHT_TITLE_PAD;
/* Now x changes to be position from the left */ /* Now x changes to be position from the left */
x = fgeom->left_width; x = fgeom->left_width;
@ -251,10 +277,10 @@ calc_geometry (MetaFrameInfo *info,
fgeom->menu_rect.height = 0; fgeom->menu_rect.height = 0;
} }
fgeom->title_rect.x = x + BUTTON_PAD; fgeom->title_rect.x = x + LEFT_TITLE_PAD;
fgeom->title_rect.y = VERTICAL_TITLE_PAD; fgeom->title_rect.y = ABOVE_TITLE_PAD;
fgeom->title_rect.width = title_right_edge - fgeom->title_rect.x; fgeom->title_rect.width = title_right_edge - fgeom->title_rect.x;
fgeom->title_rect.height = fgeom->top_height - VERTICAL_TITLE_PAD * 2; fgeom->title_rect.height = fgeom->top_height - ABOVE_TITLE_PAD - BELOW_TITLE_PAD;
if (fgeom->title_rect.width < 0) if (fgeom->title_rect.width < 0)
fgeom->title_rect.width = 0; fgeom->title_rect.width = 0;
@ -299,10 +325,11 @@ draw_vline (MetaFrameInfo *info,
int y2, int y2,
int x) int x)
{ {
/* From GTK+ */
int thickness_light; int thickness_light;
int thickness_dark; int thickness_dark;
int i; int i;
/* From GTK+ */
thickness_light = 1; thickness_light = 1;
thickness_dark = 1; thickness_dark = 1;
@ -413,11 +440,56 @@ default_expose_frame (MetaFrameInfo *info,
xoff = info->xoffset; xoff = info->xoffset;
yoff = info->yoffset; yoff = info->yoffset;
/* Black line around outside to give definition */
XDrawRectangle (info->display,
info->drawable,
screen_data->black_gc,
xoff, yoff,
info->width - 1,
info->height - 1);
/* Light GC on top/left edges */
XDrawLine (info->display,
info->drawable,
screen_data->light_gc,
xoff + 1, yoff + 1,
xoff + 1, yoff + info->height - 2);
XDrawLine (info->display,
info->drawable,
screen_data->light_gc,
xoff + 1, yoff + 1,
xoff + info->width - 2, yoff + 1);
/* Dark GC on bottom/right edges */
XDrawLine (info->display,
info->drawable,
screen_data->dark_gc,
xoff + info->width - 2, yoff + 1,
xoff + info->width - 2, yoff + info->height - 2);
XDrawLine (info->display,
info->drawable,
screen_data->dark_gc,
xoff + 1, yoff + info->height - 2,
xoff + info->width - 2, yoff + info->height - 2);
if (info->flags & META_FRAME_HAS_FOCUS)
{
/* Black line around inside while we have focus */
XDrawRectangle (info->display,
info->drawable,
screen_data->black_gc,
xoff + fgeom.left_width - 1,
yoff + fgeom.top_height - 1,
info->width - fgeom.right_width - fgeom.left_width + 1,
info->height - fgeom.bottom_height - fgeom.top_height + 1);
}
if (fgeom.title_rect.width > 0 && fgeom.title_rect.height > 0) if (fgeom.title_rect.width > 0 && fgeom.title_rect.height > 0)
{ {
int layout_y; int layout_y;
MetaRectangle clip; MetaRectangle clip;
GC layout_gc;
/* center vertically */ /* center vertically */
layout_y = fgeom.title_rect.y + layout_y = fgeom.title_rect.y +
(fgeom.title_rect.height - d->layout_height) / 2; (fgeom.title_rect.height - d->layout_height) / 2;
@ -426,17 +498,28 @@ default_expose_frame (MetaFrameInfo *info,
clip.x += xoff; clip.x += xoff;
clip.y += yoff; clip.y += yoff;
clip.width -= HORIZONTAL_TEXT_PAD; clip.width -= HORIZONTAL_TEXT_PAD;
layout_gc = screen_data->text_gc;
set_clip (info->display, screen_data->text_gc, &clip);
if (info->flags & META_FRAME_HAS_FOCUS) if (info->flags & META_FRAME_HAS_FOCUS)
{ {
/* FIXME use STATE_SELECTED */ layout_gc = screen_data->selected_text_gc;
/* Draw blue background */
XFillRectangle (info->display,
info->drawable,
screen_data->selected_gc,
xoff + fgeom.title_rect.x,
yoff + fgeom.title_rect.y,
fgeom.title_rect.width,
fgeom.title_rect.height);
} }
set_clip (info->display, layout_gc, &clip);
pango_x_render_layout (info->display, pango_x_render_layout (info->display,
info->drawable, info->drawable,
screen_data->text_gc, layout_gc,
d->layout, d->layout,
xoff + fgeom.title_rect.x + HORIZONTAL_TEXT_PAD, xoff + fgeom.title_rect.x + HORIZONTAL_TEXT_PAD,
yoff + layout_y); yoff + layout_y);
@ -580,6 +663,11 @@ default_release_screen (Screen *screen)
{ {
XFreeGC (DisplayOfScreen (screen), screen_data->text_gc); XFreeGC (DisplayOfScreen (screen), screen_data->text_gc);
XFreeGC (DisplayOfScreen (screen), screen_data->fg_gc); XFreeGC (DisplayOfScreen (screen), screen_data->fg_gc);
XFreeGC (DisplayOfScreen (screen), screen_data->selected_gc);
XFreeGC (DisplayOfScreen (screen), screen_data->selected_text_gc);
XFreeGC (DisplayOfScreen (screen), screen_data->black_gc);
XFreeGC (DisplayOfScreen (screen), screen_data->light_gc);
XFreeGC (DisplayOfScreen (screen), screen_data->dark_gc);
} }
} }

View File

@ -33,6 +33,7 @@ static void constrain_size (MetaWindow *window,
static int update_size_hints (MetaWindow *window); static int update_size_hints (MetaWindow *window);
static int update_title (MetaWindow *window); static int update_title (MetaWindow *window);
static int update_protocols (MetaWindow *window); static int update_protocols (MetaWindow *window);
static int update_wm_hints (MetaWindow *window);
static gboolean process_configure_request (MetaWindow *window, static gboolean process_configure_request (MetaWindow *window,
int x, int y, int width, int height, int x, int y, int width, int height,
int border_width); int border_width);
@ -63,7 +64,13 @@ meta_window_new (MetaDisplay *display, Window xwindow)
XAddToSaveSet (display->xdisplay, xwindow); XAddToSaveSet (display->xdisplay, xwindow);
XSelectInput (display->xdisplay, xwindow, XSelectInput (display->xdisplay, xwindow,
PropertyChangeMask); PropertyChangeMask |
EnterWindowMask | LeaveWindowMask |
FocusChangeMask);
/* Get rid of any borders */
if (attrs.border_width != 0)
XSetWindowBorderWidth (display->xdisplay, xwindow, 0);
if (meta_error_trap_pop (display) != Success) if (meta_error_trap_pop (display) != Success)
{ {
@ -96,12 +103,15 @@ meta_window_new (MetaDisplay *display, Window xwindow)
} }
g_assert (window->screen); g_assert (window->screen);
/* Remember this rect is the actual window size */
window->rect.x = attrs.x; window->rect.x = attrs.x;
window->rect.y = attrs.y; window->rect.y = attrs.y;
window->rect.width = attrs.width; window->rect.width = attrs.width;
window->rect.height = attrs.height; window->rect.height = attrs.height;
/* And border width, size_hints are the "request" */
window->border_width = attrs.border_width;
window->size_hints.x = attrs.x; window->size_hints.x = attrs.x;
window->size_hints.y = attrs.y; window->size_hints.y = attrs.y;
window->size_hints.width = attrs.width; window->size_hints.width = attrs.width;
@ -116,13 +126,15 @@ meta_window_new (MetaDisplay *display, Window xwindow)
window->desc = g_strdup_printf ("0x%lx", window->xwindow); window->desc = g_strdup_printf ("0x%lx", window->xwindow);
window->frame = NULL; window->frame = NULL;
window->has_focus = FALSE;
meta_display_register_x_window (display, &window->xwindow, window); meta_display_register_x_window (display, &window->xwindow, window);
update_size_hints (window); update_size_hints (window);
update_title (window); update_title (window);
update_protocols (window); update_protocols (window);
update_wm_hints (window);
meta_window_resize (window, window->size_hints.width, window->size_hints.height); meta_window_resize (window, window->size_hints.width, window->size_hints.height);
meta_window_ensure_frame (window); meta_window_ensure_frame (window);
@ -189,6 +201,82 @@ meta_window_resize (MetaWindow *window,
} }
} }
void
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);
meta_error_trap_pop (window->display);
}
void
meta_window_focus (MetaWindow *window,
Time timestamp)
{
meta_verbose ("Setting input focus to window %s, input: %d take_focus: %d\n",
window->desc, window->input, window->take_focus);
if (window->input)
{
meta_error_trap_push (window->display);
if (window->take_focus)
{
meta_window_send_icccm_message (window,
window->display->atom_wm_take_focus,
timestamp);
}
else
{
XSetInputFocus (window->display->xdisplay,
window->xwindow,
RevertToParent,
timestamp);
}
meta_error_trap_pop (window->display);
}
}
void
meta_window_send_icccm_message (MetaWindow *window,
Atom atom,
Time timestamp)
{
/* This comment and code are from twm, copyright
* Open Group, Evans & Sutherland, etc.
*/
/*
* ICCCM Client Messages - Section 4.2.8 of the ICCCM dictates that all
* client messages will have the following form:
*
* event type ClientMessage
* message type _XA_WM_PROTOCOLS
* window tmp->w
* format 32
* data[0] message atom
* data[1] time stamp
*/
XClientMessageEvent ev;
/* This should always be error trapped. */
g_return_if_fail (window->display->error_traps != NULL);
ev.type = ClientMessage;
ev.window = window->xwindow;
ev.message_type = window->display->atom_wm_protocols;
ev.format = 32;
ev.data.l[0] = atom;
ev.data.l[1] = timestamp;
XSendEvent (window->display->xdisplay,
window->xwindow, False, 0, (XEvent*) &ev);
}
gboolean gboolean
meta_window_configure_request (MetaWindow *window, meta_window_configure_request (MetaWindow *window,
XEvent *event) XEvent *event)
@ -208,100 +296,6 @@ meta_window_property_notify (MetaWindow *window,
return process_property_notify (window, &event->xproperty); return process_property_notify (window, &event->xproperty);
} }
gboolean
meta_window_event (MetaWindow *window,
XEvent *event)
{
if (event->xany.window != window->xwindow)
return FALSE;
switch (event->type)
{
case KeyPress:
break;
case KeyRelease:
break;
case ButtonPress:
break;
case ButtonRelease:
break;
case MotionNotify:
break;
case EnterNotify:
break;
case LeaveNotify:
break;
case FocusIn:
break;
case FocusOut:
break;
case KeymapNotify:
break;
case Expose:
break;
case GraphicsExpose:
break;
case NoExpose:
break;
case VisibilityNotify:
break;
case CreateNotify:
break;
case DestroyNotify:
return TRUE;
break;
case UnmapNotify:
/* Window withdrawn */
meta_window_free (window);
return TRUE;
break;
case MapNotify:
break;
case MapRequest:
break;
case ReparentNotify:
break;
case ConfigureNotify:
break;
case ConfigureRequest:
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;
}
/* Didn't use this event */
return FALSE;
}
static gboolean static gboolean
process_property_notify (MetaWindow *window, process_property_notify (MetaWindow *window,
XPropertyEvent *event) XPropertyEvent *event)
@ -383,8 +377,7 @@ process_configure_request (MetaWindow *window,
/* Note that x, y is the corner of the window border, /* Note that x, y is the corner of the window border,
* and width, height is the size of the window inside * and width, height is the size of the window inside
* its border, but that we always deny border requests * its border, but that we always deny border requests
* because we don't believe in clients who use lame-ass * and give windows a border of 0
* X features like that.
*/ */
window->border_width = border_width; window->border_width = border_width;
@ -727,6 +720,30 @@ update_protocols (MetaWindow *window)
return meta_error_trap_pop (window->display); return meta_error_trap_pop (window->display);
} }
static int
update_wm_hints (MetaWindow *window)
{
XWMHints *hints;
/* Fill in defaults */
window->input = FALSE;
meta_error_trap_push (window->display);
hints = XGetWMHints (window->display->xdisplay,
window->xwindow);
if (hints)
{
window->input = (hints->flags & InputHint) != 0;
/* FIXME there are a few others there. */
XFree (hints);
}
return meta_error_trap_pop (window->display);
}
static void static void
constrain_size (MetaWindow *window, constrain_size (MetaWindow *window,
int width, int height, int width, int height,

View File

@ -41,7 +41,14 @@ struct _MetaWindow
guint iconic : 1; guint iconic : 1;
guint take_focus : 1; guint take_focus : 1;
guint delete_window : 1; guint delete_window : 1;
/* Globally active / No input */
guint input : 1;
/* this flag tracks receipt of focus_in focus_out and
* determines whether we draw the focus
*/
guint has_focus : 1;
/* The size we set the window to last. */ /* The size we set the window to last. */
MetaRectangle rect; MetaRectangle rect;
@ -59,6 +66,16 @@ void meta_window_hide (MetaWindow *window);
void meta_window_resize (MetaWindow *window, void meta_window_resize (MetaWindow *window,
int w, int w,
int h); int h);
void meta_window_delete (MetaWindow *window,
Time timestamp);
void meta_window_focus (MetaWindow *window,
Time timestamp);
/* Sends a client message */
void meta_window_send_icccm_message (MetaWindow *window,
Atom atom,
Time timestamp);
gboolean meta_window_configure_request (MetaWindow *window, gboolean meta_window_configure_request (MetaWindow *window,
XEvent *event); XEvent *event);