mirror of
https://github.com/brl/mutter.git
synced 2024-11-24 00:50:42 -05:00
...
This commit is contained in:
parent
e47c4d16a2
commit
ce7c53bf1a
@ -62,6 +62,9 @@ PKG_CHECK_MODULES(METACITY, $PANGO_PACKAGES)
|
|||||||
# Check for shaped window extension
|
# Check for shaped window extension
|
||||||
AC_CHECK_LIB(Xext, XShapeCombineMask, AC_DEFINE(HAVE_SHAPE_EXT),,$METACITY_LIBS)
|
AC_CHECK_LIB(Xext, XShapeCombineMask, AC_DEFINE(HAVE_SHAPE_EXT),,$METACITY_LIBS)
|
||||||
|
|
||||||
|
HOST_ALIAS=$host_alias
|
||||||
|
AC_SUBST(HOST_ALIAS)
|
||||||
|
|
||||||
AC_OUTPUT([
|
AC_OUTPUT([
|
||||||
Makefile
|
Makefile
|
||||||
intl/Makefile
|
intl/Makefile
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
SUBDIRS=uislave
|
SUBDIRS=uislave
|
||||||
|
|
||||||
INCLUDES=@METACITY_CFLAGS@
|
INCLUDES=@METACITY_CFLAGS@ -DMETACITY_LIBEXECDIR=\"$(libexecdir)\" -DHOST_ALIAS=\"@HOST_ALIAS@\"
|
||||||
|
|
||||||
metacity_SOURCES= \
|
metacity_SOURCES= \
|
||||||
api.c \
|
api.c \
|
||||||
|
163
src/display.c
163
src/display.c
@ -24,14 +24,18 @@
|
|||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "screen.h"
|
#include "screen.h"
|
||||||
#include "window.h"
|
#include "window.h"
|
||||||
|
#include "frame.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,
|
||||||
XEvent *event);
|
XEvent *event);
|
||||||
static void event_queue_callback (MetaEventQueue *queue,
|
static void event_queue_callback (MetaEventQueue *queue,
|
||||||
XEvent *event,
|
XEvent *event,
|
||||||
gpointer data);
|
gpointer data);
|
||||||
|
static Window event_get_modified_window (MetaDisplay *display,
|
||||||
|
XEvent *event);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static gint
|
static gint
|
||||||
@ -63,7 +67,7 @@ meta_display_open (const char *name)
|
|||||||
GSList *screens;
|
GSList *screens;
|
||||||
GSList *tmp;
|
GSList *tmp;
|
||||||
int i;
|
int i;
|
||||||
char *atom_names[] = { "_NET_WM_NAME" };
|
char *atom_names[] = { "_NET_WM_NAME", "WM_PROTOCOLS", "WM_TAKE_FOCUS", "WM_DELETE_WINDOW" };
|
||||||
Atom atoms[G_N_ELEMENTS(atom_names)];
|
Atom atoms[G_N_ELEMENTS(atom_names)];
|
||||||
|
|
||||||
meta_verbose ("Opening display '%s'\n", XDisplayName (name));
|
meta_verbose ("Opening display '%s'\n", XDisplayName (name));
|
||||||
@ -82,6 +86,10 @@ meta_display_open (const char *name)
|
|||||||
|
|
||||||
display = g_new (MetaDisplay, 1);
|
display = g_new (MetaDisplay, 1);
|
||||||
|
|
||||||
|
/* here we use XDisplayName which is what the user
|
||||||
|
* probably put in, vs. DisplayString(display) which is
|
||||||
|
* canonicalized by XOpenDisplay()
|
||||||
|
*/
|
||||||
display->name = g_strdup (XDisplayName (name));
|
display->name = g_strdup (XDisplayName (name));
|
||||||
display->xdisplay = xdisplay;
|
display->xdisplay = xdisplay;
|
||||||
display->error_traps = NULL;
|
display->error_traps = NULL;
|
||||||
@ -277,27 +285,27 @@ event_queue_callback (MetaEventQueue *queue,
|
|||||||
{
|
{
|
||||||
MetaWindow *window;
|
MetaWindow *window;
|
||||||
MetaDisplay *display;
|
MetaDisplay *display;
|
||||||
gboolean is_root;
|
Window modified;
|
||||||
|
|
||||||
display = data;
|
display = data;
|
||||||
|
|
||||||
if (dump_events)
|
if (dump_events)
|
||||||
meta_spew_event (display, event);
|
meta_spew_event (display, event);
|
||||||
|
|
||||||
is_root = meta_display_screen_for_root (display, event->xany.window) != NULL;
|
modified = event_get_modified_window (display, event);
|
||||||
|
|
||||||
|
if (modified != None)
|
||||||
|
window = meta_display_lookup_x_window (display, modified);
|
||||||
|
else
|
||||||
window = NULL;
|
window = NULL;
|
||||||
|
|
||||||
if (!is_root)
|
if (window &&
|
||||||
|
window->frame &&
|
||||||
|
modified == window->frame->xwindow)
|
||||||
{
|
{
|
||||||
if (window == NULL)
|
meta_frame_event (window->frame, event);
|
||||||
window = meta_display_lookup_x_window (display, event->xany.window);
|
|
||||||
|
|
||||||
if (window != NULL)
|
|
||||||
{
|
|
||||||
if (meta_window_event (window, event))
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
switch (event->type)
|
switch (event->type)
|
||||||
{
|
{
|
||||||
@ -332,28 +340,59 @@ event_queue_callback (MetaEventQueue *queue,
|
|||||||
case CreateNotify:
|
case CreateNotify:
|
||||||
break;
|
break;
|
||||||
case DestroyNotify:
|
case DestroyNotify:
|
||||||
|
if (window)
|
||||||
|
meta_window_free (window); /* Unmanage destroyed window */
|
||||||
break;
|
break;
|
||||||
case UnmapNotify:
|
case UnmapNotify:
|
||||||
|
if (window)
|
||||||
|
meta_window_free (window); /* Unmanage withdrawn window */
|
||||||
break;
|
break;
|
||||||
case MapNotify:
|
case MapNotify:
|
||||||
break;
|
break;
|
||||||
case MapRequest:
|
case MapRequest:
|
||||||
if (is_root && !event->xmap.override_redirect)
|
|
||||||
{
|
|
||||||
/* Window requested mapping. Manage it if we haven't. Note that
|
|
||||||
* meta_window_new() can return NULL
|
|
||||||
*/
|
|
||||||
window = meta_display_lookup_x_window (display,
|
|
||||||
event->xmaprequest.window);
|
|
||||||
if (window == NULL)
|
if (window == NULL)
|
||||||
window = meta_window_new (display, event->xmaprequest.window);
|
window = meta_window_new (display, event->xmaprequest.window);
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case ReparentNotify:
|
case ReparentNotify:
|
||||||
break;
|
break;
|
||||||
case ConfigureNotify:
|
case ConfigureNotify:
|
||||||
|
if (event->xconfigure.override_redirect)
|
||||||
|
{
|
||||||
|
/* Unmanage it, override_redirect was toggled on?
|
||||||
|
* Can this happen?
|
||||||
|
*/
|
||||||
|
meta_window_free (window);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case ConfigureRequest:
|
case ConfigureRequest:
|
||||||
|
/* This comment and code is found in both twm and fvwm */
|
||||||
|
/*
|
||||||
|
* According to the July 27, 1988 ICCCM draft, we should ignore size and
|
||||||
|
* position fields in the WM_NORMAL_HINTS property when we map a window.
|
||||||
|
* Instead, we'll read the current geometry. Therefore, we should respond
|
||||||
|
* to configuration requests for windows which have never been mapped.
|
||||||
|
*/
|
||||||
|
if (window == NULL)
|
||||||
|
{
|
||||||
|
unsigned int xwcm;
|
||||||
|
XWindowChanges xwc;
|
||||||
|
|
||||||
|
xwcm = event->xconfigurerequest.value_mask &
|
||||||
|
(CWX | CWY | CWWidth | CWHeight | CWBorderWidth);
|
||||||
|
|
||||||
|
xwc.x = event->xconfigurerequest.x;
|
||||||
|
xwc.y = event->xconfigurerequest.y;
|
||||||
|
xwc.width = event->xconfigurerequest.width;
|
||||||
|
xwc.height = event->xconfigurerequest.height;
|
||||||
|
xwc.border_width = event->xconfigurerequest.border_width;
|
||||||
|
|
||||||
|
XConfigureWindow (display->xdisplay, event->xconfigurerequest.window,
|
||||||
|
xwcm, &xwc);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
meta_window_configure_request (window, event);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case GravityNotify:
|
case GravityNotify:
|
||||||
break;
|
break;
|
||||||
@ -364,6 +403,8 @@ event_queue_callback (MetaEventQueue *queue,
|
|||||||
case CirculateRequest:
|
case CirculateRequest:
|
||||||
break;
|
break;
|
||||||
case PropertyNotify:
|
case PropertyNotify:
|
||||||
|
if (window)
|
||||||
|
meta_window_property_notify (window, event);
|
||||||
break;
|
break;
|
||||||
case SelectionClear:
|
case SelectionClear:
|
||||||
break;
|
break;
|
||||||
@ -382,6 +423,80 @@ event_queue_callback (MetaEventQueue *queue,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return the window this has to do with, if any, rather
|
||||||
|
* than the frame or root window that was selecting
|
||||||
|
* for substructure
|
||||||
|
*/
|
||||||
|
static Window
|
||||||
|
event_get_modified_window (MetaDisplay *display,
|
||||||
|
XEvent *event)
|
||||||
|
{
|
||||||
|
switch (event->type)
|
||||||
|
{
|
||||||
|
case KeyPress:
|
||||||
|
case KeyRelease:
|
||||||
|
case ButtonPress:
|
||||||
|
case ButtonRelease:
|
||||||
|
case MotionNotify:
|
||||||
|
case EnterNotify:
|
||||||
|
case LeaveNotify:
|
||||||
|
case FocusIn:
|
||||||
|
case FocusOut:
|
||||||
|
case KeymapNotify:
|
||||||
|
case Expose:
|
||||||
|
case GraphicsExpose:
|
||||||
|
case NoExpose:
|
||||||
|
case VisibilityNotify:
|
||||||
|
case ResizeRequest:
|
||||||
|
case PropertyNotify:
|
||||||
|
case SelectionClear:
|
||||||
|
case SelectionRequest:
|
||||||
|
case SelectionNotify:
|
||||||
|
case ColormapNotify:
|
||||||
|
case ClientMessage:
|
||||||
|
return event->xany.window;
|
||||||
|
|
||||||
|
case CreateNotify:
|
||||||
|
return event->xcreatewindow.window;
|
||||||
|
|
||||||
|
case DestroyNotify:
|
||||||
|
return event->xdestroywindow.window;
|
||||||
|
|
||||||
|
case UnmapNotify:
|
||||||
|
return event->xunmap.window;
|
||||||
|
|
||||||
|
case MapNotify:
|
||||||
|
return event->xmap.window;
|
||||||
|
|
||||||
|
case MapRequest:
|
||||||
|
return event->xmaprequest.window;
|
||||||
|
|
||||||
|
case ReparentNotify:
|
||||||
|
return event->xreparent.window;
|
||||||
|
|
||||||
|
case ConfigureNotify:
|
||||||
|
return event->xconfigure.window;
|
||||||
|
|
||||||
|
case ConfigureRequest:
|
||||||
|
return event->xconfigurerequest.window;
|
||||||
|
|
||||||
|
case GravityNotify:
|
||||||
|
return event->xgravity.window;
|
||||||
|
|
||||||
|
case CirculateNotify:
|
||||||
|
return event->xcirculate.window;
|
||||||
|
|
||||||
|
case CirculateRequest:
|
||||||
|
return event->xcirculaterequest.window;
|
||||||
|
|
||||||
|
case MappingNotify:
|
||||||
|
return None;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
meta_spew_event (MetaDisplay *display,
|
meta_spew_event (MetaDisplay *display,
|
||||||
XEvent *event)
|
XEvent *event)
|
||||||
@ -465,6 +580,14 @@ meta_spew_event (MetaDisplay *display,
|
|||||||
break;
|
break;
|
||||||
case ConfigureRequest:
|
case ConfigureRequest:
|
||||||
name = "ConfigureRequest";
|
name = "ConfigureRequest";
|
||||||
|
extra = g_strdup_printf ("parent: 0x%lx window: 0x%lx x: %d y: %d w: %d h: %d border: %d",
|
||||||
|
event->xconfigurerequest.parent,
|
||||||
|
event->xconfigurerequest.window,
|
||||||
|
event->xconfigurerequest.x,
|
||||||
|
event->xconfigurerequest.y,
|
||||||
|
event->xconfigurerequest.width,
|
||||||
|
event->xconfigurerequest.height,
|
||||||
|
event->xconfigurerequest.border_width);
|
||||||
break;
|
break;
|
||||||
case GravityNotify:
|
case GravityNotify:
|
||||||
name = "GravityNotify";
|
name = "GravityNotify";
|
||||||
|
@ -31,6 +31,7 @@ typedef struct _MetaDisplay MetaDisplay;
|
|||||||
typedef struct _MetaFrame MetaFrame;
|
typedef struct _MetaFrame MetaFrame;
|
||||||
typedef struct _MetaScreen MetaScreen;
|
typedef struct _MetaScreen MetaScreen;
|
||||||
typedef struct _MetaWindow MetaWindow;
|
typedef struct _MetaWindow MetaWindow;
|
||||||
|
typedef struct _MetaUISlave MetaUISlave;
|
||||||
|
|
||||||
struct _MetaDisplay
|
struct _MetaDisplay
|
||||||
{
|
{
|
||||||
@ -38,6 +39,9 @@ struct _MetaDisplay
|
|||||||
Display *xdisplay;
|
Display *xdisplay;
|
||||||
|
|
||||||
Atom atom_net_wm_name;
|
Atom atom_net_wm_name;
|
||||||
|
Atom atom_wm_protocols;
|
||||||
|
Atom atom_wm_take_focus;
|
||||||
|
Atom atom_wm_delete_window;
|
||||||
|
|
||||||
/*< private-ish >*/
|
/*< private-ish >*/
|
||||||
MetaEventQueue *events;
|
MetaEventQueue *events;
|
||||||
|
348
src/frame.c
348
src/frame.c
@ -37,109 +37,145 @@ meta_frame_init_info (MetaFrame *frame,
|
|||||||
info->height = frame->rect.height;
|
info->height = frame->rect.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static void
|
||||||
meta_window_ensure_frame (MetaWindow *window)
|
meta_frame_calc_initial_pos (MetaFrame *frame,
|
||||||
|
int child_root_x, int child_root_y)
|
||||||
|
{
|
||||||
|
MetaWindow *window;
|
||||||
|
|
||||||
|
window = frame->window;
|
||||||
|
|
||||||
|
switch (window->size_hints.win_gravity)
|
||||||
|
{
|
||||||
|
case NorthWestGravity:
|
||||||
|
frame->rect.x = child_root_x;
|
||||||
|
frame->rect.y = child_root_y;
|
||||||
|
break;
|
||||||
|
case NorthGravity:
|
||||||
|
frame->rect.x = child_root_x - frame->rect.width / 2;
|
||||||
|
frame->rect.y = child_root_y;
|
||||||
|
break;
|
||||||
|
case NorthEastGravity:
|
||||||
|
frame->rect.x = child_root_x - frame->rect.width;
|
||||||
|
frame->rect.y = child_root_y;
|
||||||
|
break;
|
||||||
|
case WestGravity:
|
||||||
|
frame->rect.x = child_root_x;
|
||||||
|
frame->rect.y = child_root_y - frame->rect.height / 2;
|
||||||
|
break;
|
||||||
|
case CenterGravity:
|
||||||
|
frame->rect.x = child_root_x - frame->rect.width / 2;
|
||||||
|
frame->rect.y = child_root_y - frame->rect.height / 2;
|
||||||
|
break;
|
||||||
|
case EastGravity:
|
||||||
|
frame->rect.x = child_root_x - frame->rect.width;
|
||||||
|
frame->rect.y = child_root_y - frame->rect.height / 2;
|
||||||
|
break;
|
||||||
|
case SouthWestGravity:
|
||||||
|
frame->rect.x = child_root_x;
|
||||||
|
frame->rect.y = child_root_y - frame->rect.height;
|
||||||
|
break;
|
||||||
|
case SouthGravity:
|
||||||
|
frame->rect.x = child_root_x - frame->rect.width / 2;
|
||||||
|
frame->rect.y = child_root_y - frame->rect.height;
|
||||||
|
break;
|
||||||
|
case SouthEastGravity:
|
||||||
|
frame->rect.x = child_root_x - frame->rect.width;
|
||||||
|
frame->rect.y = child_root_y - frame->rect.height;
|
||||||
|
break;
|
||||||
|
case StaticGravity:
|
||||||
|
default:
|
||||||
|
frame->rect.x = child_root_x - frame->child_x;
|
||||||
|
frame->rect.y = child_root_y - frame->child_y;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_frame_calc_geometry (MetaFrame *frame,
|
||||||
|
int child_width, int child_height,
|
||||||
|
MetaFrameGeometry *geomp)
|
||||||
{
|
{
|
||||||
MetaFrame *frame;
|
|
||||||
int child_x, child_y;
|
|
||||||
unsigned long background_pixel;
|
|
||||||
XSetWindowAttributes attrs;
|
|
||||||
MetaFrameInfo info;
|
MetaFrameInfo info;
|
||||||
MetaFrameGeometry geom;
|
MetaFrameGeometry geom;
|
||||||
|
MetaWindow *window;
|
||||||
|
|
||||||
if (window->frame)
|
/* Remember this is called from the constructor
|
||||||
return;
|
* pre-window-creation.
|
||||||
|
*/
|
||||||
|
|
||||||
frame = g_new (MetaFrame, 1);
|
window = frame->window;
|
||||||
|
|
||||||
frame->window = window;
|
frame->rect.width = child_width;
|
||||||
|
frame->rect.height = child_height;
|
||||||
/* Fill these in for the theme engine's benefit */
|
|
||||||
frame->xwindow = None;
|
|
||||||
frame->rect.width = window->rect.width;
|
|
||||||
frame->rect.height = window->rect.height;
|
|
||||||
|
|
||||||
meta_frame_init_info (frame, &info);
|
meta_frame_init_info (frame, &info);
|
||||||
|
|
||||||
|
if (!frame->theme_acquired)
|
||||||
|
frame->theme_data = window->screen->engine->acquire_frame (&info);
|
||||||
|
|
||||||
geom.left_width = 0;
|
geom.left_width = 0;
|
||||||
geom.right_width = 0;
|
geom.right_width = 0;
|
||||||
geom.top_height = 0;
|
geom.top_height = 0;
|
||||||
geom.bottom_height = 0;
|
geom.bottom_height = 0;
|
||||||
geom.background_pixel = BlackPixel (frame->window->display->xdisplay,
|
geom.background_pixel = BlackPixel (window->display->xdisplay,
|
||||||
frame->window->screen->number);
|
window->screen->number);
|
||||||
|
|
||||||
geom.shape_mask = None;
|
geom.shape_mask = None;
|
||||||
|
|
||||||
frame->theme_data = window->screen->engine->acquire_frame (&info);
|
|
||||||
window->screen->engine->fill_frame_geometry (&info, &geom,
|
window->screen->engine->fill_frame_geometry (&info, &geom,
|
||||||
frame->theme_data);
|
frame->theme_data);
|
||||||
|
|
||||||
child_x = geom.left_width;
|
frame->child_x = geom.left_width;
|
||||||
child_y = geom.top_height;
|
frame->child_y = geom.top_height;
|
||||||
|
|
||||||
frame->rect.width = window->rect.width + geom.left_width + geom.right_width;
|
frame->rect.width = frame->rect.width + geom.left_width + geom.right_width;
|
||||||
frame->rect.height = window->rect.height + geom.top_height + geom.bottom_height;
|
frame->rect.height = frame->rect.height + geom.top_height + geom.bottom_height;
|
||||||
|
|
||||||
background_pixel = geom.background_pixel;
|
*geomp = geom;
|
||||||
|
|
||||||
switch (window->size_hints.win_gravity)
|
|
||||||
{
|
|
||||||
case NorthWestGravity:
|
|
||||||
frame->rect.x = window->rect.x;
|
|
||||||
frame->rect.y = window->rect.y;
|
|
||||||
break;
|
|
||||||
case NorthGravity:
|
|
||||||
frame->rect.x = window->rect.x - frame->rect.width / 2;
|
|
||||||
frame->rect.y = window->rect.y;
|
|
||||||
break;
|
|
||||||
case NorthEastGravity:
|
|
||||||
frame->rect.x = window->rect.x - frame->rect.width;
|
|
||||||
frame->rect.y = window->rect.y;
|
|
||||||
break;
|
|
||||||
case WestGravity:
|
|
||||||
frame->rect.x = window->rect.x;
|
|
||||||
frame->rect.y = window->rect.y - frame->rect.height / 2;
|
|
||||||
break;
|
|
||||||
case CenterGravity:
|
|
||||||
frame->rect.x = window->rect.x - frame->rect.width / 2;
|
|
||||||
frame->rect.y = window->rect.y - frame->rect.height / 2;
|
|
||||||
break;
|
|
||||||
case EastGravity:
|
|
||||||
frame->rect.x = window->rect.x - frame->rect.width;
|
|
||||||
frame->rect.y = window->rect.y - frame->rect.height / 2;
|
|
||||||
break;
|
|
||||||
case SouthWestGravity:
|
|
||||||
frame->rect.x = window->rect.x;
|
|
||||||
frame->rect.y = window->rect.y - frame->rect.height;
|
|
||||||
break;
|
|
||||||
case SouthGravity:
|
|
||||||
frame->rect.x = window->rect.x - frame->rect.width / 2;
|
|
||||||
frame->rect.y = window->rect.y - frame->rect.height;
|
|
||||||
break;
|
|
||||||
case SouthEastGravity:
|
|
||||||
frame->rect.x = window->rect.x - frame->rect.width;
|
|
||||||
frame->rect.y = window->rect.y - frame->rect.height;
|
|
||||||
break;
|
|
||||||
case StaticGravity:
|
|
||||||
default:
|
|
||||||
frame->rect.x = window->rect.x - child_x;
|
|
||||||
frame->rect.y = window->rect.y - child_y;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
meta_verbose ("Creating frame %d,%d %dx%d around window 0x%lx %d,%d %dx%d with child position inside frame %d,%d and gravity %d\n",
|
void
|
||||||
|
meta_window_ensure_frame (MetaWindow *window)
|
||||||
|
{
|
||||||
|
MetaFrame *frame;
|
||||||
|
XSetWindowAttributes attrs;
|
||||||
|
MetaFrameGeometry geom;
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
/* Fill in values that calc_geometry will use */
|
||||||
|
frame->window = window;
|
||||||
|
frame->xwindow = None;
|
||||||
|
frame->theme_acquired = FALSE;
|
||||||
|
|
||||||
|
/* This fills in frame->rect as well. */
|
||||||
|
meta_frame_calc_geometry (frame,
|
||||||
|
window->rect.width,
|
||||||
|
window->rect.height,
|
||||||
|
&geom);
|
||||||
|
|
||||||
|
meta_frame_calc_initial_pos (frame, window->rect.x, window->rect.y);
|
||||||
|
|
||||||
|
meta_verbose ("Will create frame %d,%d %dx%d around window %s %d,%d %dx%d with child position inside frame %d,%d and gravity %d\n",
|
||||||
frame->rect.x, frame->rect.y,
|
frame->rect.x, frame->rect.y,
|
||||||
frame->rect.width, frame->rect.height,
|
frame->rect.width, frame->rect.height,
|
||||||
window->xwindow,
|
window->desc,
|
||||||
window->rect.x, window->rect.y,
|
window->rect.x, window->rect.y,
|
||||||
window->rect.width, window->rect.height,
|
window->rect.width, window->rect.height,
|
||||||
child_x, child_y,
|
frame->child_x, frame->child_y,
|
||||||
window->size_hints.win_gravity);
|
window->size_hints.win_gravity);
|
||||||
|
|
||||||
attrs.background_pixel = background_pixel;
|
attrs.background_pixel = geom.background_pixel;
|
||||||
attrs.event_mask =
|
attrs.event_mask =
|
||||||
StructureNotifyMask | ExposureMask |
|
StructureNotifyMask | SubstructureNotifyMask | ExposureMask |
|
||||||
ButtonPressMask | ButtonReleaseMask |
|
ButtonPressMask | ButtonReleaseMask | OwnerGrabButtonMask |
|
||||||
PointerMotionMask | PointerMotionHintMask;
|
PointerMotionMask | PointerMotionHintMask;
|
||||||
|
|
||||||
frame->xwindow = XCreateWindow (window->display->xdisplay,
|
frame->xwindow = XCreateWindow (window->display->xdisplay,
|
||||||
@ -177,10 +213,14 @@ meta_window_ensure_frame (MetaWindow *window)
|
|||||||
XReparentWindow (window->display->xdisplay,
|
XReparentWindow (window->display->xdisplay,
|
||||||
window->xwindow,
|
window->xwindow,
|
||||||
frame->xwindow,
|
frame->xwindow,
|
||||||
child_x,
|
frame->child_x,
|
||||||
child_y);
|
frame->child_y);
|
||||||
meta_error_trap_pop (window->display);
|
meta_error_trap_pop (window->display);
|
||||||
|
|
||||||
|
/* Update window's location */
|
||||||
|
window->rect.x = frame->child_x;
|
||||||
|
window->rect.y = frame->child_y;
|
||||||
|
|
||||||
/* stick frame to the window */
|
/* stick frame to the window */
|
||||||
window->frame = frame;
|
window->frame = frame;
|
||||||
|
|
||||||
@ -246,6 +286,90 @@ meta_frame_move (MetaFrame *frame,
|
|||||||
root_x, root_y);
|
root_x, root_y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Just a chunk of process_configure_event in window.c,
|
||||||
|
* moved here since it's the part that deals with
|
||||||
|
* the frame.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
meta_frame_child_configure_request (MetaFrame *frame)
|
||||||
|
{
|
||||||
|
MetaFrameGeometry geom;
|
||||||
|
|
||||||
|
/* This fills in frame->rect as well. */
|
||||||
|
meta_frame_calc_geometry (frame,
|
||||||
|
frame->window->size_hints.width,
|
||||||
|
frame->window->size_hints.height,
|
||||||
|
&geom);
|
||||||
|
|
||||||
|
meta_frame_calc_initial_pos (frame,
|
||||||
|
frame->window->size_hints.x,
|
||||||
|
frame->window->size_hints.y);
|
||||||
|
|
||||||
|
XMoveResizeWindow (frame->window->display->xdisplay,
|
||||||
|
frame->xwindow,
|
||||||
|
frame->rect.x,
|
||||||
|
frame->rect.y,
|
||||||
|
frame->rect.width,
|
||||||
|
frame->rect.height);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_frame_recalc_now (MetaFrame *frame)
|
||||||
|
{
|
||||||
|
int old_child_x, old_child_y;
|
||||||
|
MetaFrameGeometry geom;
|
||||||
|
XSetWindowAttributes attrs;
|
||||||
|
|
||||||
|
old_child_x = frame->child_x;
|
||||||
|
old_child_y = frame->child_y;
|
||||||
|
|
||||||
|
/* This fills in frame->rect as well. */
|
||||||
|
meta_frame_calc_geometry (frame,
|
||||||
|
frame->window->rect.width,
|
||||||
|
frame->window->rect.height,
|
||||||
|
&geom);
|
||||||
|
|
||||||
|
/* See if we need to move the frame to keep child in
|
||||||
|
* a constant position
|
||||||
|
*/
|
||||||
|
if (old_child_x != frame->child_x)
|
||||||
|
frame->rect.x += (frame->child_x - old_child_x);
|
||||||
|
if (old_child_y != frame->child_y)
|
||||||
|
frame->rect.y += (frame->child_y - old_child_y);
|
||||||
|
|
||||||
|
XMoveResizeWindow (frame->window->display->xdisplay,
|
||||||
|
frame->xwindow,
|
||||||
|
frame->rect.x,
|
||||||
|
frame->rect.y,
|
||||||
|
frame->rect.width,
|
||||||
|
frame->rect.height);
|
||||||
|
|
||||||
|
attrs.background_pixel = geom.background_pixel;
|
||||||
|
XChangeWindowAttributes (frame->window->display->xdisplay,
|
||||||
|
frame->xwindow,
|
||||||
|
CWBackPixel,
|
||||||
|
&attrs);
|
||||||
|
|
||||||
|
meta_verbose ("Frame of %s recalculated to %d,%d %d x %d child %d,%d\n",
|
||||||
|
frame->window->desc, frame->rect.x, frame->rect.y,
|
||||||
|
frame->rect.width, frame->rect.height,
|
||||||
|
frame->child_x, frame->child_y);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_frame_queue_recalc (MetaFrame *frame)
|
||||||
|
{
|
||||||
|
/* FIXME */
|
||||||
|
meta_frame_recalc_now (frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_frame_queue_draw (MetaFrame *frame)
|
||||||
|
{
|
||||||
|
/* FIXME */
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
frame_query_root_pointer (MetaFrame *frame,
|
frame_query_root_pointer (MetaFrame *frame,
|
||||||
int *x, int *y)
|
int *x, int *y)
|
||||||
@ -283,6 +407,37 @@ frame_get_control (MetaFrame *frame,
|
|||||||
frame->theme_data);
|
frame->theme_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
update_move (MetaFrame *frame)
|
||||||
|
{
|
||||||
|
int x, y;
|
||||||
|
int new_x, new_y;
|
||||||
|
frame_query_root_pointer (frame, &x, &y);
|
||||||
|
|
||||||
|
new_x = frame->rect.x + (x - frame->last_x);
|
||||||
|
new_y = frame->rect.y + (y - frame->last_y);
|
||||||
|
frame->last_x = x;
|
||||||
|
frame->last_y = y;
|
||||||
|
|
||||||
|
meta_frame_move (frame, new_x, new_y);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
update_resize_se (MetaFrame *frame)
|
||||||
|
{
|
||||||
|
int x, y;
|
||||||
|
int new_w, new_h;
|
||||||
|
|
||||||
|
frame_query_root_pointer (frame, &x, &y);
|
||||||
|
|
||||||
|
new_w = frame->window->rect.width + (x - frame->last_x);
|
||||||
|
new_h = frame->window->rect.height + (y - frame->last_y);
|
||||||
|
frame->last_x = x;
|
||||||
|
frame->last_y = y;
|
||||||
|
|
||||||
|
meta_window_resize (frame->window, new_w, new_h);
|
||||||
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
meta_frame_event (MetaFrame *frame,
|
meta_frame_event (MetaFrame *frame,
|
||||||
XEvent *event)
|
XEvent *event)
|
||||||
@ -323,15 +478,32 @@ meta_frame_event (MetaFrame *frame,
|
|||||||
else if (control == META_FRAME_CONTROL_RESIZE_SE &&
|
else if (control == META_FRAME_CONTROL_RESIZE_SE &&
|
||||||
event->xbutton.button == 1)
|
event->xbutton.button == 1)
|
||||||
{
|
{
|
||||||
/* FIXME begin a resize */
|
|
||||||
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->last_x = event->xbutton.x_root;
|
||||||
|
frame->last_y = event->xbutton.y_root;
|
||||||
|
frame->start_button = event->xbutton.button;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ButtonRelease:
|
case ButtonRelease:
|
||||||
if (event->xbutton.button == frame->start_button)
|
if (event->xbutton.button == frame->start_button)
|
||||||
{
|
{
|
||||||
|
switch (frame->action)
|
||||||
|
{
|
||||||
|
case META_FRAME_ACTION_MOVING:
|
||||||
|
update_move (frame);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case META_FRAME_ACTION_RESIZING_SE:
|
||||||
|
update_resize_se (frame);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
frame->action = META_FRAME_ACTION_NONE;
|
frame->action = META_FRAME_ACTION_NONE;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -339,18 +511,11 @@ meta_frame_event (MetaFrame *frame,
|
|||||||
switch (frame->action)
|
switch (frame->action)
|
||||||
{
|
{
|
||||||
case META_FRAME_ACTION_MOVING:
|
case META_FRAME_ACTION_MOVING:
|
||||||
{
|
update_move (frame);
|
||||||
int x, y;
|
break;
|
||||||
int new_x, new_y;
|
|
||||||
frame_query_root_pointer (frame, &x, &y);
|
|
||||||
|
|
||||||
new_x = frame->rect.x + (x - frame->last_x);
|
case META_FRAME_ACTION_RESIZING_SE:
|
||||||
new_y = frame->rect.y + (y - frame->last_y);
|
update_resize_se (frame);
|
||||||
frame->last_x = x;
|
|
||||||
frame->last_y = y;
|
|
||||||
|
|
||||||
meta_frame_move (frame, new_x, new_y);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -388,11 +553,16 @@ meta_frame_event (MetaFrame *frame,
|
|||||||
case CreateNotify:
|
case CreateNotify:
|
||||||
break;
|
break;
|
||||||
case DestroyNotify:
|
case DestroyNotify:
|
||||||
|
{
|
||||||
|
MetaDisplay *display;
|
||||||
|
|
||||||
meta_warning ("Unexpected destruction of frame 0x%lx, not sure if this should silently fail or be considered a bug\n", frame->xwindow);
|
meta_warning ("Unexpected destruction of frame 0x%lx, not sure if this should silently fail or be considered a bug\n", frame->xwindow);
|
||||||
meta_error_trap_push (frame->window->display);
|
display = frame->window->display;
|
||||||
|
meta_error_trap_push (display);
|
||||||
meta_window_destroy_frame (frame->window);
|
meta_window_destroy_frame (frame->window);
|
||||||
meta_error_trap_pop (frame->window->display);
|
meta_error_trap_pop (display);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case UnmapNotify:
|
case UnmapNotify:
|
||||||
frame->action = META_FRAME_ACTION_NONE;
|
frame->action = META_FRAME_ACTION_NONE;
|
||||||
|
19
src/frame.h
19
src/frame.h
@ -28,7 +28,7 @@ typedef enum
|
|||||||
{
|
{
|
||||||
META_FRAME_ACTION_NONE,
|
META_FRAME_ACTION_NONE,
|
||||||
META_FRAME_ACTION_MOVING,
|
META_FRAME_ACTION_MOVING,
|
||||||
META_FRAME_ACTION_RESIZING
|
META_FRAME_ACTION_RESIZING_SE
|
||||||
} MetaFrameAction;
|
} MetaFrameAction;
|
||||||
|
|
||||||
struct _MetaFrame
|
struct _MetaFrame
|
||||||
@ -43,6 +43,8 @@ struct _MetaFrame
|
|||||||
* frame, not the result of ConfigureNotify
|
* frame, not the result of ConfigureNotify
|
||||||
*/
|
*/
|
||||||
MetaRectangle rect;
|
MetaRectangle rect;
|
||||||
|
int child_x;
|
||||||
|
int child_y;
|
||||||
|
|
||||||
gpointer theme_data;
|
gpointer theme_data;
|
||||||
|
|
||||||
@ -50,16 +52,27 @@ struct _MetaFrame
|
|||||||
/* reference point for drags */
|
/* reference point for drags */
|
||||||
int last_x, last_y;
|
int last_x, last_y;
|
||||||
int start_button;
|
int start_button;
|
||||||
|
|
||||||
|
guint theme_acquired : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
void meta_window_ensure_frame (MetaWindow *window);
|
void meta_window_ensure_frame (MetaWindow *window);
|
||||||
void meta_window_destroy_frame (MetaWindow *window);
|
void meta_window_destroy_frame (MetaWindow *window);
|
||||||
|
|
||||||
void meta_frame_move (MetaFrame *frame,
|
void meta_frame_move (MetaFrame *frame,
|
||||||
int root_x,
|
int root_x,
|
||||||
int root_y);
|
int root_y);
|
||||||
|
void meta_frame_child_configure_request (MetaFrame *frame);
|
||||||
|
void meta_frame_recalc_now (MetaFrame *frame);
|
||||||
|
void meta_frame_queue_recalc (MetaFrame *frame);
|
||||||
|
void meta_frame_queue_draw (MetaFrame *frame);
|
||||||
gboolean meta_frame_event (MetaFrame *frame,
|
gboolean meta_frame_event (MetaFrame *frame,
|
||||||
XEvent *event);
|
XEvent *event);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
#! /bin/bash
|
#! /bin/bash
|
||||||
|
|
||||||
Xnest :1 -scrns 2 -geometry 270x270 &
|
Xnest :1 -scrns 2 -geometry 270x270 &
|
||||||
sleep 1
|
METACITY_UISLAVE_DIR=./uislave DISPLAY=:1 unst libtool --mode=execute gdb ./metacity
|
||||||
DISPLAY=:1 unst $1 ./metacity
|
|
||||||
killall Xnest
|
killall Xnest
|
||||||
|
80
src/screen.c
80
src/screen.c
@ -24,11 +24,19 @@
|
|||||||
#include "errors.h"
|
#include "errors.h"
|
||||||
#include "window.h"
|
#include "window.h"
|
||||||
#include "colors.h"
|
#include "colors.h"
|
||||||
|
#include "uislave.h"
|
||||||
|
|
||||||
#include <X11/cursorfont.h>
|
#include <X11/cursorfont.h>
|
||||||
#include <locale.h>
|
#include <locale.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
static void ui_slave_func (MetaUISlave *uislave,
|
||||||
|
MetaMessage *message,
|
||||||
|
gpointer data);
|
||||||
|
static char* get_screen_name (MetaDisplay *display,
|
||||||
|
int number);
|
||||||
|
|
||||||
|
|
||||||
MetaScreen*
|
MetaScreen*
|
||||||
meta_screen_new (MetaDisplay *display,
|
meta_screen_new (MetaDisplay *display,
|
||||||
int number)
|
int number)
|
||||||
@ -83,14 +91,19 @@ meta_screen_new (MetaDisplay *display,
|
|||||||
|
|
||||||
screen->display = display;
|
screen->display = display;
|
||||||
screen->number = number;
|
screen->number = number;
|
||||||
|
screen->screen_name = get_screen_name (display, number);
|
||||||
screen->xscreen = ScreenOfDisplay (xdisplay, number);
|
screen->xscreen = ScreenOfDisplay (xdisplay, number);
|
||||||
screen->xroot = xroot;
|
screen->xroot = xroot;
|
||||||
screen->pango_context = NULL;
|
screen->pango_context = NULL;
|
||||||
|
|
||||||
screen->engine = &meta_default_engine;
|
screen->engine = &meta_default_engine;
|
||||||
|
|
||||||
meta_verbose ("Added screen %d on display '%s' root 0x%lx\n",
|
screen->uislave = meta_ui_slave_new (screen->screen_name,
|
||||||
screen->number, screen->display->name, screen->xroot);
|
ui_slave_func,
|
||||||
|
screen);
|
||||||
|
|
||||||
|
meta_verbose ("Added screen %d ('%s') root 0x%lx\n",
|
||||||
|
screen->number, screen->screen_name, screen->xroot);
|
||||||
|
|
||||||
return screen;
|
return screen;
|
||||||
}
|
}
|
||||||
@ -98,8 +111,10 @@ meta_screen_new (MetaDisplay *display,
|
|||||||
void
|
void
|
||||||
meta_screen_free (MetaScreen *screen)
|
meta_screen_free (MetaScreen *screen)
|
||||||
{
|
{
|
||||||
|
meta_ui_slave_free (screen->uislave);
|
||||||
if (screen->pango_context)
|
if (screen->pango_context)
|
||||||
g_object_unref (G_OBJECT (screen->pango_context));
|
g_object_unref (G_OBJECT (screen->pango_context));
|
||||||
|
g_free (screen->screen_name);
|
||||||
g_free (screen);
|
g_free (screen);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -256,3 +271,64 @@ meta_screen_for_x_screen (Screen *xscreen)
|
|||||||
|
|
||||||
return meta_display_screen_for_x_screen (display, xscreen);
|
return meta_display_screen_for_x_screen (display, xscreen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ui_slave_func (MetaUISlave *uislave,
|
||||||
|
MetaMessage *message,
|
||||||
|
gpointer data)
|
||||||
|
{
|
||||||
|
switch (message->header.message_code)
|
||||||
|
{
|
||||||
|
case MetaMessageCheckCode:
|
||||||
|
meta_verbose ("Received UI slave check message version: %s host alias: %s messages version: %d\n",
|
||||||
|
message->check.metacity_version,
|
||||||
|
message->check.host_alias,
|
||||||
|
message->check.messages_version);
|
||||||
|
|
||||||
|
if (strcmp (message->check.metacity_version, VERSION) != 0 ||
|
||||||
|
strcmp (message->check.host_alias, HOST_ALIAS) != 0 ||
|
||||||
|
message->check.messages_version != META_MESSAGES_VERSION)
|
||||||
|
{
|
||||||
|
meta_warning ("metacity-uislave has the wrong version; must use the one compiled with metacity\n");
|
||||||
|
meta_ui_slave_disable (uislave);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
meta_verbose ("Received unhandled message from UI slave: %d\n",
|
||||||
|
message->header.message_code);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static char*
|
||||||
|
get_screen_name (MetaDisplay *display,
|
||||||
|
int number)
|
||||||
|
{
|
||||||
|
char *p;
|
||||||
|
char *dname;
|
||||||
|
char *scr;
|
||||||
|
|
||||||
|
/* DisplayString gives us a sort of canonical display,
|
||||||
|
* vs. the user-entered name from XDisplayName()
|
||||||
|
*/
|
||||||
|
dname = g_strdup (DisplayString (display->xdisplay));
|
||||||
|
|
||||||
|
/* Change display name to specify this screen.
|
||||||
|
*/
|
||||||
|
p = strrchr (dname, ':');
|
||||||
|
if (p)
|
||||||
|
{
|
||||||
|
p = strchr (p, '.');
|
||||||
|
if (p)
|
||||||
|
*p = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
scr = g_strdup_printf ("%s.%d", dname, number);
|
||||||
|
|
||||||
|
g_free (dname);
|
||||||
|
|
||||||
|
return scr;
|
||||||
|
}
|
||||||
|
@ -29,6 +29,7 @@ struct _MetaScreen
|
|||||||
{
|
{
|
||||||
MetaDisplay *display;
|
MetaDisplay *display;
|
||||||
int number;
|
int number;
|
||||||
|
char *screen_name;
|
||||||
Screen *xscreen;
|
Screen *xscreen;
|
||||||
Window xroot;
|
Window xroot;
|
||||||
|
|
||||||
@ -40,6 +41,8 @@ struct _MetaScreen
|
|||||||
* root window)
|
* root window)
|
||||||
*/
|
*/
|
||||||
PangoContext *pango_context;
|
PangoContext *pango_context;
|
||||||
|
|
||||||
|
MetaUISlave *uislave;
|
||||||
};
|
};
|
||||||
|
|
||||||
MetaScreen* meta_screen_new (MetaDisplay *display,
|
MetaScreen* meta_screen_new (MetaDisplay *display,
|
||||||
|
505
src/uislave.c
505
src/uislave.c
@ -20,10 +20,513 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "uislave.h"
|
#include "uislave.h"
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <signal.h>
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
READ_FAILED = 0, /* FALSE */
|
||||||
|
READ_OK,
|
||||||
|
READ_EOF
|
||||||
|
} ReadResult;
|
||||||
|
|
||||||
|
static void respawn_child (MetaUISlave *uislave);
|
||||||
|
static gboolean output_callback (GIOChannel *source,
|
||||||
|
GIOCondition condition,
|
||||||
|
gpointer data);
|
||||||
|
static gboolean error_callback (GIOChannel *source,
|
||||||
|
GIOCondition condition,
|
||||||
|
gpointer data);
|
||||||
|
static void kill_child (MetaUISlave *uislave);
|
||||||
|
static void reset_vals (MetaUISlave *uislave);
|
||||||
|
static ReadResult read_data (GString *str,
|
||||||
|
gint fd);
|
||||||
|
|
||||||
|
/* Message queue main loop source */
|
||||||
|
static gboolean mq_prepare (GSource *source,
|
||||||
|
gint *timeout);
|
||||||
|
static gboolean mq_check (GSource *source);
|
||||||
|
static gboolean mq_dispatch (GSource *source,
|
||||||
|
GSourceFunc callback,
|
||||||
|
gpointer user_data);
|
||||||
|
static void mq_destroy (GSource *source);
|
||||||
|
|
||||||
|
static GSourceFuncs mq_funcs = {
|
||||||
|
mq_prepare,
|
||||||
|
mq_check,
|
||||||
|
mq_dispatch,
|
||||||
|
mq_destroy
|
||||||
|
};
|
||||||
|
|
||||||
MetaUISlave*
|
MetaUISlave*
|
||||||
meta_ui_slave_new (const char *display_name)
|
meta_ui_slave_new (const char *display_name,
|
||||||
|
MetaUISlaveFunc func,
|
||||||
|
gpointer data)
|
||||||
{
|
{
|
||||||
|
MetaUISlave *uislave;
|
||||||
|
GSource *source;
|
||||||
|
|
||||||
|
source = g_source_new (&mq_funcs, sizeof (MetaUISlave));
|
||||||
|
|
||||||
|
uislave = (MetaUISlave*) source;
|
||||||
|
|
||||||
|
uislave->display_name = g_strdup (display_name);
|
||||||
|
uislave->queue = g_queue_new ();
|
||||||
|
uislave->buf = g_string_new ("");
|
||||||
|
uislave->current_message = g_string_new ("");
|
||||||
|
|
||||||
|
reset_vals (uislave);
|
||||||
|
|
||||||
|
/* This may fail; all UISlave functions become no-ops
|
||||||
|
* if uislave->child_pids == 0, and metacity just runs
|
||||||
|
* with no UI features other than window borders.
|
||||||
|
*/
|
||||||
|
respawn_child (uislave);
|
||||||
|
|
||||||
|
g_source_set_priority (source, G_PRIORITY_DEFAULT);
|
||||||
|
g_source_set_can_recurse (source, TRUE);
|
||||||
|
|
||||||
|
g_source_set_callback (source, (GSourceFunc) func, data, NULL);
|
||||||
|
|
||||||
|
g_source_attach (source, NULL);
|
||||||
|
|
||||||
|
return uislave;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_ui_slave_free (MetaUISlave *uislave)
|
||||||
|
{
|
||||||
|
GSource *source;
|
||||||
|
|
||||||
|
source = (GSource*) uislave;
|
||||||
|
|
||||||
|
g_source_destroy (source);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_ui_slave_disable (MetaUISlave *uislave)
|
||||||
|
{
|
||||||
|
/* Change UI slave into "black hole" mode,
|
||||||
|
* we found out it's hosed for some reason.
|
||||||
|
*/
|
||||||
|
kill_child (uislave);
|
||||||
|
uislave->no_respawn = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
respawn_child (MetaUISlave *uislave)
|
||||||
|
{
|
||||||
|
GError *error;
|
||||||
|
const char *uislavedir;
|
||||||
|
char *argv[] = { "./metacity-uislave", NULL };
|
||||||
|
char *envp[2] = { NULL, NULL };
|
||||||
|
int child_pid, inpipe, outpipe, errpipe;
|
||||||
|
|
||||||
|
if (uislave->no_respawn)
|
||||||
|
return;
|
||||||
|
|
||||||
|
uislavedir = g_getenv ("METACITY_UISLAVE_DIR");
|
||||||
|
if (uislavedir == NULL)
|
||||||
|
uislavedir = METACITY_LIBEXECDIR;
|
||||||
|
|
||||||
|
envp[0] = g_strconcat ("DISPLAY=", uislave->display_name, NULL);
|
||||||
|
|
||||||
|
error = NULL;
|
||||||
|
if (g_spawn_async_with_pipes (uislavedir,
|
||||||
|
argv,
|
||||||
|
envp,
|
||||||
|
/* flags */
|
||||||
|
0,
|
||||||
|
/* setup func, data */
|
||||||
|
NULL, NULL,
|
||||||
|
&child_pid,
|
||||||
|
&inpipe, &outpipe, &errpipe,
|
||||||
|
&error))
|
||||||
|
{
|
||||||
|
uislave->child_pid = child_pid;
|
||||||
|
uislave->in_pipe = inpipe;
|
||||||
|
uislave->err_pipe = errpipe;
|
||||||
|
uislave->out_poll.fd = outpipe;
|
||||||
|
uislave->out_poll.events = G_IO_IN;
|
||||||
|
|
||||||
|
uislave->err_channel = g_io_channel_unix_new (errpipe);
|
||||||
|
|
||||||
|
uislave->errwatch = g_io_add_watch (uislave->err_channel,
|
||||||
|
G_IO_IN,
|
||||||
|
error_callback,
|
||||||
|
uislave);
|
||||||
|
|
||||||
|
meta_verbose ("Spawned UI slave with PID %d\n", uislave->child_pid);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
meta_warning ("Failed to create user interface process: %s\n",
|
||||||
|
error->message);
|
||||||
|
g_error_free (error);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_free (envp[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
append_pending (MetaUISlave *uislave)
|
||||||
|
{
|
||||||
|
int needed;
|
||||||
|
|
||||||
|
needed = uislave->current_required_len - uislave->current_message->len;
|
||||||
|
g_assert (needed >= 0);
|
||||||
|
|
||||||
|
needed = MIN (needed, uislave->buf->len);
|
||||||
|
|
||||||
|
/* Move data from buf to current_message */
|
||||||
|
g_string_append_len (uislave->current_message,
|
||||||
|
uislave->buf->str,
|
||||||
|
needed);
|
||||||
|
g_string_erase (uislave->buf,
|
||||||
|
0, needed);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
output_callback (GIOChannel *source,
|
||||||
|
GIOCondition condition,
|
||||||
|
gpointer data)
|
||||||
|
{
|
||||||
|
/* Read messages from slave */
|
||||||
|
MetaUISlave *uislave;
|
||||||
|
ReadResult res;
|
||||||
|
|
||||||
|
uislave = data;
|
||||||
|
|
||||||
|
res = read_data (uislave->buf, uislave->out_pipe);
|
||||||
|
|
||||||
|
switch (res)
|
||||||
|
{
|
||||||
|
case READ_OK:
|
||||||
|
meta_verbose ("Read data from slave, %d bytes in buffer\n",
|
||||||
|
uislave->buf->len);
|
||||||
|
break;
|
||||||
|
case READ_EOF:
|
||||||
|
meta_verbose ("EOF reading stdout from slave process\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case READ_FAILED:
|
||||||
|
/* read_data printed the error */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
error_callback (GIOChannel *source,
|
||||||
|
GIOCondition condition,
|
||||||
|
gpointer data)
|
||||||
|
{
|
||||||
|
/* Relay slave errors to WM stderr */
|
||||||
|
#define BUFSIZE 1024
|
||||||
|
MetaUISlave *uislave;
|
||||||
|
char buf[1024];
|
||||||
|
int n;
|
||||||
|
|
||||||
|
uislave = data;
|
||||||
|
|
||||||
|
/* Classic loop from Stevens */
|
||||||
|
n = read (uislave->err_pipe, buf, BUFSIZE);
|
||||||
|
if (n > 0)
|
||||||
|
{
|
||||||
|
if (write (2, buf, n) != n)
|
||||||
|
; /* error, but printing a message to stderr will hardly help. */
|
||||||
|
}
|
||||||
|
else if (n < 0)
|
||||||
|
meta_warning (_("Error reading errors from UI slave: %s\n"),
|
||||||
|
g_strerror (errno));
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
#undef BUFSIZE
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
mq_queue_messages (MetaUISlave *uislave)
|
||||||
|
{
|
||||||
|
if (uislave->buf->len == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (uislave->current_message->len > 0)
|
||||||
|
{
|
||||||
|
/* We had a pending message. */
|
||||||
|
append_pending (uislave);
|
||||||
|
}
|
||||||
|
else if (uislave->buf->len > META_MESSAGE_ESCAPE_LEN)
|
||||||
|
{
|
||||||
|
/* See if we can start a current message */
|
||||||
|
const char *p;
|
||||||
|
int esc_pos;
|
||||||
|
const char *esc;
|
||||||
|
MetaMessageHeader header;
|
||||||
|
|
||||||
|
/* note that the string from the UI slave includes the nul byte */
|
||||||
|
esc = META_MESSAGE_ESCAPE;
|
||||||
|
|
||||||
|
esc_pos = 0;
|
||||||
|
p = uislave->buf->str;
|
||||||
|
while (p != (uislave->buf->str + uislave->buf->len) &&
|
||||||
|
esc_pos < META_MESSAGE_ESCAPE_LEN)
|
||||||
|
{
|
||||||
|
if (*p != esc[esc_pos])
|
||||||
|
esc_pos = 0;
|
||||||
|
else
|
||||||
|
++esc_pos;
|
||||||
|
|
||||||
|
++p;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (esc_pos == META_MESSAGE_ESCAPE_LEN)
|
||||||
|
{
|
||||||
|
/* We found an entire escape sequence; can safely toss
|
||||||
|
* out the entire buffer before it
|
||||||
|
*/
|
||||||
|
int ignored;
|
||||||
|
|
||||||
|
ignored = p - uislave->buf->str;
|
||||||
|
ignored -= META_MESSAGE_ESCAPE_LEN;
|
||||||
|
|
||||||
|
g_assert (ignored >= 0);
|
||||||
|
|
||||||
|
if (ignored > 0)
|
||||||
|
{
|
||||||
|
meta_verbose ("Ignoring %d bytes from UI slave\n",
|
||||||
|
ignored);
|
||||||
|
|
||||||
|
g_string_erase (uislave->buf, 0, ignored);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (esc_pos == 0)
|
||||||
|
{
|
||||||
|
/* End of buffer doesn't begin an escape sequence;
|
||||||
|
* toss out entire buffer.
|
||||||
|
*/
|
||||||
|
meta_verbose ("Ignoring %d bytes from UI slave\n",
|
||||||
|
uislave->buf->len);
|
||||||
|
g_string_truncate (uislave->buf, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (uislave->buf->len < (META_MESSAGE_ESCAPE_LEN + sizeof (MetaMessageHeader)))
|
||||||
|
return; /* Not enough data yet. */
|
||||||
|
|
||||||
|
memcpy (&header, uislave->buf->str + META_MESSAGE_ESCAPE_LEN, sizeof (MetaMessageHeader));
|
||||||
|
|
||||||
|
/* Length includes the header even though it's in the header. */
|
||||||
|
meta_verbose ("Read header code: %d length: %d from UI slave\n",
|
||||||
|
header.message_code, header.length);
|
||||||
|
|
||||||
|
uislave->current_required_len = header.length;
|
||||||
|
g_string_erase (uislave->buf, 0, META_MESSAGE_ESCAPE_LEN);
|
||||||
|
|
||||||
|
append_pending (uislave);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_assert (uislave->current_message->len <= uislave->current_required_len);
|
||||||
|
|
||||||
|
if (uislave->current_required_len > 0 &&
|
||||||
|
uislave->current_message->len == uislave->current_required_len)
|
||||||
|
{
|
||||||
|
MetaMessage *message;
|
||||||
|
|
||||||
|
message = g_new (MetaMessage, 1);
|
||||||
|
|
||||||
|
memcpy (message,
|
||||||
|
uislave->current_message->str, uislave->current_message->len);
|
||||||
|
|
||||||
|
g_queue_push_tail (uislave->queue, message);
|
||||||
|
|
||||||
|
meta_verbose ("Added %d-byte message to queue\n",
|
||||||
|
uislave->current_message->len);
|
||||||
|
|
||||||
|
uislave->current_required_len = 0;
|
||||||
|
g_string_truncate (uislave->current_message, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
mq_messages_pending (MetaUISlave *uislave)
|
||||||
|
{
|
||||||
|
return uislave->queue->length > 0 || uislave->buf->len > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
mq_prepare (GSource *source, gint *timeout)
|
||||||
|
{
|
||||||
|
MetaUISlave *uislave;
|
||||||
|
|
||||||
|
uislave = (MetaUISlave*) source;
|
||||||
|
|
||||||
|
*timeout = -1;
|
||||||
|
|
||||||
|
return mq_messages_pending (uislave);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
mq_check (GSource *source)
|
||||||
|
{
|
||||||
|
MetaUISlave *uislave;
|
||||||
|
|
||||||
|
uislave = (MetaUISlave*) source;
|
||||||
|
|
||||||
|
return mq_messages_pending (uislave);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
mq_dispatch (GSource *source, GSourceFunc callback, gpointer user_data)
|
||||||
|
{
|
||||||
|
MetaUISlave *uislave;
|
||||||
|
|
||||||
|
uislave = (MetaUISlave*) source;
|
||||||
|
|
||||||
|
mq_queue_messages (uislave);
|
||||||
|
|
||||||
|
if (uislave->queue->length > 0)
|
||||||
|
{
|
||||||
|
MetaUISlaveFunc func;
|
||||||
|
MetaMessage *msg;
|
||||||
|
static int count = 0;
|
||||||
|
|
||||||
|
++count;
|
||||||
|
|
||||||
|
msg = g_queue_pop_head (uislave->queue);
|
||||||
|
func = (MetaUISlaveFunc) callback;
|
||||||
|
|
||||||
|
(* func) (uislave, msg, user_data);
|
||||||
|
|
||||||
|
meta_verbose ("%d messages dispatched\n", count);
|
||||||
|
|
||||||
|
g_free (msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
kill_child (MetaUISlave *uislave)
|
||||||
|
{
|
||||||
|
if (uislave->outwatch != 0)
|
||||||
|
g_source_remove (uislave->outwatch);
|
||||||
|
|
||||||
|
if (uislave->errwatch != 0)
|
||||||
|
g_source_remove (uislave->errwatch);
|
||||||
|
|
||||||
|
if (uislave->out_channel)
|
||||||
|
g_io_channel_unref (uislave->out_channel);
|
||||||
|
|
||||||
|
if (uislave->err_channel)
|
||||||
|
g_io_channel_unref (uislave->err_channel);
|
||||||
|
|
||||||
|
if (uislave->out_pipe >= 0)
|
||||||
|
close (uislave->out_pipe);
|
||||||
|
|
||||||
|
if (uislave->in_pipe >= 0)
|
||||||
|
close (uislave->in_pipe);
|
||||||
|
|
||||||
|
if (uislave->err_pipe >= 0)
|
||||||
|
close (uislave->err_pipe);
|
||||||
|
|
||||||
|
while (uislave->queue->length > 0)
|
||||||
|
{
|
||||||
|
MetaMessage *msg;
|
||||||
|
|
||||||
|
msg = g_queue_pop_head (uislave->queue);
|
||||||
|
|
||||||
|
g_free (msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (uislave->buf->len > 0)
|
||||||
|
g_string_truncate (uislave->buf, 0);
|
||||||
|
|
||||||
|
if (uislave->current_message->len > 0)
|
||||||
|
g_string_truncate (uislave->current_message, 0);
|
||||||
|
|
||||||
|
if (uislave->child_pid > 0)
|
||||||
|
{
|
||||||
|
/* don't care if this fails except in verbose mode */
|
||||||
|
if (kill (uislave->child_pid, SIGTERM) != 0)
|
||||||
|
{
|
||||||
|
meta_verbose ("Kill of UI slave process %d failed: %s\n",
|
||||||
|
uislave->child_pid, g_strerror (errno));
|
||||||
|
}
|
||||||
|
|
||||||
|
uislave->child_pid = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
reset_vals (uislave);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
reset_vals (MetaUISlave *uislave)
|
||||||
|
{
|
||||||
|
uislave->child_pid = 0;
|
||||||
|
uislave->in_pipe = -1;
|
||||||
|
uislave->out_pipe = -1;
|
||||||
|
uislave->err_pipe = -1;
|
||||||
|
uislave->no_respawn = FALSE;
|
||||||
|
uislave->out_channel = NULL;
|
||||||
|
uislave->err_channel = NULL;
|
||||||
|
uislave->outwatch = 0;
|
||||||
|
uislave->errwatch = 0;
|
||||||
|
uislave->current_required_len = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
mq_destroy (GSource *source)
|
||||||
|
{
|
||||||
|
MetaUISlave *uislave;
|
||||||
|
|
||||||
|
uislave = (MetaUISlave*) source;
|
||||||
|
|
||||||
|
meta_verbose ("Deleting UI slave for display '%s'\n",
|
||||||
|
uislave->display_name);
|
||||||
|
|
||||||
|
kill_child (uislave);
|
||||||
|
|
||||||
|
g_string_free (uislave->buf, TRUE);
|
||||||
|
g_string_free (uislave->current_message, TRUE);
|
||||||
|
|
||||||
|
g_queue_free (uislave->queue);
|
||||||
|
|
||||||
|
g_free (uislave->display_name);
|
||||||
|
|
||||||
|
/* source itself is freed by glib */
|
||||||
|
}
|
||||||
|
|
||||||
|
static ReadResult
|
||||||
|
read_data (GString *str,
|
||||||
|
gint fd)
|
||||||
|
{
|
||||||
|
#define BUFSIZE 16
|
||||||
|
gint bytes;
|
||||||
|
gchar buf[BUFSIZE];
|
||||||
|
|
||||||
|
again:
|
||||||
|
|
||||||
|
bytes = read (fd, &buf, BUFSIZE);
|
||||||
|
|
||||||
|
if (bytes == 0)
|
||||||
|
return READ_EOF;
|
||||||
|
else if (bytes > 0)
|
||||||
|
{
|
||||||
|
g_string_append_len (str, buf, bytes);
|
||||||
|
return READ_OK;
|
||||||
|
}
|
||||||
|
else if (bytes < 0 && errno == EINTR)
|
||||||
|
goto again;
|
||||||
|
else if (bytes < 0)
|
||||||
|
{
|
||||||
|
meta_warning (_("Failed to read data from UI slave: %s\n"),
|
||||||
|
g_strerror (errno));
|
||||||
|
|
||||||
|
return READ_FAILED;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return READ_OK;
|
||||||
}
|
}
|
||||||
|
@ -23,17 +23,39 @@
|
|||||||
#define META_UI_SLAVE_H
|
#define META_UI_SLAVE_H
|
||||||
|
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include <X11/Xlib.h>
|
#include "uislave/messages.h"
|
||||||
#include <X11/Xutil.h>
|
#include "display.h"
|
||||||
|
|
||||||
typedef struct _MetaUISlave MetaUISlave;
|
typedef void (* MetaUISlaveFunc) (MetaUISlave *uislave,
|
||||||
|
MetaMessage *message,
|
||||||
|
gpointer data);
|
||||||
|
|
||||||
struct _MetaUISlave
|
struct _MetaUISlave
|
||||||
{
|
{
|
||||||
|
GSource source;
|
||||||
|
|
||||||
char *display_name;
|
char *display_name;
|
||||||
|
int child_pid;
|
||||||
|
int in_pipe;
|
||||||
|
int err_pipe;
|
||||||
|
GPollFD out_poll;
|
||||||
|
GIOChannel *err_channel;
|
||||||
|
unsigned int errwatch;
|
||||||
|
GQueue *queue;
|
||||||
|
GString *buf;
|
||||||
|
GString *current_message;
|
||||||
|
int current_required_len;
|
||||||
|
/* if we determine that our available slave is hosed,
|
||||||
|
* set this bit.
|
||||||
|
*/
|
||||||
|
guint no_respawn : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
MetaUISlave* meta_ui_slave_new (const char *display_name);
|
MetaUISlave* meta_ui_slave_new (const char *display_name,
|
||||||
|
MetaUISlaveFunc func,
|
||||||
|
gpointer data);
|
||||||
|
void meta_ui_slave_free (MetaUISlave *uislave);
|
||||||
|
void meta_ui_slave_disable (MetaUISlave *uislave);
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
|
|
||||||
INCLUDES=@UISLAVE_CFLAGS@
|
INCLUDES=@UISLAVE_CFLAGS@ -DHOST_ALIAS=\"@HOST_ALIAS@\"
|
||||||
|
|
||||||
metacity_uislave_SOURCES = \
|
metacity_uislave_SOURCES = \
|
||||||
main.c
|
main.c \
|
||||||
|
messages.c \
|
||||||
|
messages.h
|
||||||
|
|
||||||
libexec_PROGRAMS=metacity-uislave
|
libexec_PROGRAMS=metacity-uislave
|
||||||
|
|
||||||
|
@ -19,9 +19,75 @@
|
|||||||
* 02111-1307, USA.
|
* 02111-1307, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "messages.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_ui_warning (const char *format, ...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
gchar *str;
|
||||||
|
|
||||||
|
g_return_if_fail (format != NULL);
|
||||||
|
|
||||||
|
va_start (args, format);
|
||||||
|
str = g_strdup_vprintf (format, args);
|
||||||
|
va_end (args);
|
||||||
|
|
||||||
|
fputs (str, stderr);
|
||||||
|
|
||||||
|
g_free (str);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main (int argc, char **argv)
|
main (int argc, char **argv)
|
||||||
{
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* report our nature to the window manager */
|
||||||
|
meta_message_send_check ();
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
/* Try breaking message queue system. */
|
||||||
|
i = 0;
|
||||||
|
while (i < 100)
|
||||||
|
{
|
||||||
|
meta_message_send_check ();
|
||||||
|
if (g_random_boolean ())
|
||||||
|
{
|
||||||
|
int j;
|
||||||
|
if (g_random_boolean ())
|
||||||
|
j = g_random_int_range (0, 15);
|
||||||
|
else
|
||||||
|
j = g_random_int_range (0, 1000);
|
||||||
|
while (j > 0)
|
||||||
|
{
|
||||||
|
char b;
|
||||||
|
b = g_random_int_range (0, 256);
|
||||||
|
|
||||||
|
write (1, &b, 1);
|
||||||
|
--j;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
gtk_init (&argc, &argv);
|
||||||
|
|
||||||
|
gtk_main ();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
123
src/uislave/messages.c
Normal file
123
src/uislave/messages.c
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
/* Metacity UI Slave Messages */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "messages.h"
|
||||||
|
#include "main.h"
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <config.h>
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
READ_FAILED = 0, /* FALSE */
|
||||||
|
READ_OK,
|
||||||
|
READ_EOF
|
||||||
|
} ReadResult;
|
||||||
|
|
||||||
|
static ReadResult read_data (GString *str,
|
||||||
|
gint fd);
|
||||||
|
|
||||||
|
static void send_message (MetaMessage *message);
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_message_send_check (void)
|
||||||
|
{
|
||||||
|
MetaMessageCheck check;
|
||||||
|
|
||||||
|
memset (&check, 0, sizeof (check));
|
||||||
|
check.header.message_code = MetaMessageCheckCode;
|
||||||
|
check.header.length = sizeof (check);
|
||||||
|
strcpy (check.metacity_version, VERSION);
|
||||||
|
strcpy (check.host_alias, HOST_ALIAS);
|
||||||
|
check.metacity_version[META_MESSAGE_MAX_VERSION_LEN] = '\0';
|
||||||
|
check.host_alias[META_MESSAGE_MAX_HOST_ALIAS_LEN] = '\0';
|
||||||
|
check.messages_version = META_MESSAGES_VERSION;
|
||||||
|
|
||||||
|
send_message ((MetaMessage*)&check);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
write_bytes (void *buf, int bytes)
|
||||||
|
{
|
||||||
|
const char *p;
|
||||||
|
|
||||||
|
p = (char*) buf;
|
||||||
|
while (bytes > 0)
|
||||||
|
{
|
||||||
|
int written;
|
||||||
|
|
||||||
|
written = write (1, p, bytes);
|
||||||
|
|
||||||
|
if (written < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
bytes -= written;
|
||||||
|
p += written;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
send_message (MetaMessage *message)
|
||||||
|
{
|
||||||
|
/* Not much point checking for errors here. We can't
|
||||||
|
* really report them anyway.
|
||||||
|
*/
|
||||||
|
|
||||||
|
write_bytes (META_MESSAGE_ESCAPE, META_MESSAGE_ESCAPE_LEN);
|
||||||
|
write_bytes (message, message->header.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ReadResult
|
||||||
|
read_data (GString *str,
|
||||||
|
gint fd)
|
||||||
|
{
|
||||||
|
gint bytes;
|
||||||
|
gchar buf[4096];
|
||||||
|
|
||||||
|
again:
|
||||||
|
|
||||||
|
bytes = read (fd, &buf, 4096);
|
||||||
|
|
||||||
|
if (bytes == 0)
|
||||||
|
return READ_EOF;
|
||||||
|
else if (bytes > 0)
|
||||||
|
{
|
||||||
|
g_string_append_len (str, buf, bytes);
|
||||||
|
return READ_OK;
|
||||||
|
}
|
||||||
|
else if (bytes < 0 && errno == EINTR)
|
||||||
|
goto again;
|
||||||
|
else if (bytes < 0)
|
||||||
|
{
|
||||||
|
meta_ui_warning (_("Failed to read data from window manager (%s)\n"),
|
||||||
|
g_strerror (errno));
|
||||||
|
|
||||||
|
return READ_FAILED;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return READ_OK;
|
||||||
|
}
|
115
src/uislave/messages.h
Normal file
115
src/uislave/messages.h
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
/* Metacity UI Slave Messages */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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_UI_SLAVE_MESSAGES_H
|
||||||
|
#define META_UI_SLAVE_MESSAGES_H
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
|
||||||
|
/* This header is shared between the WM and the UI slave */
|
||||||
|
/* Note that our IPC can be kind of lame; we trust both sides
|
||||||
|
* of the connection, and assume that they were compiled at the
|
||||||
|
* same time vs. the same libs on the same arch
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* We increment this when we change this header, so we can
|
||||||
|
* check for mismatched UI slave and WM
|
||||||
|
*/
|
||||||
|
#define META_MESSAGES_VERSION 1
|
||||||
|
|
||||||
|
/* We have an escape sequence, just in case some part of GTK
|
||||||
|
* decides to write to stdout, so that we have a good chance
|
||||||
|
* of surviving that. GTK probably won't print this string.
|
||||||
|
* This string has to stay the same always so we can ping
|
||||||
|
* old UI slaves.
|
||||||
|
*/
|
||||||
|
#define META_MESSAGE_ESCAPE "|~-metacity-~|"
|
||||||
|
/* len includes nul byte which is a required part of the escape */
|
||||||
|
#define META_MESSAGE_ESCAPE_LEN 15
|
||||||
|
|
||||||
|
#define META_MESSAGE_MAX_VERSION_LEN 15
|
||||||
|
#define META_MESSAGE_MAX_HOST_ALIAS_LEN 50
|
||||||
|
|
||||||
|
typedef union _MetaMessage MetaMessage;
|
||||||
|
typedef struct _MetaMessageHeader MetaMessageHeader;
|
||||||
|
typedef struct _MetaMessageCheck MetaMessageCheck;
|
||||||
|
typedef struct _MetaMessageShowTip MetaMessageShowTip;
|
||||||
|
typedef struct _MetaMessageHideTip MetaMessageHideTip;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
/* Keep NullCode and CheckCode unchanged, as with the escape sequence,
|
||||||
|
* so we can check old UI slaves.
|
||||||
|
*/
|
||||||
|
MetaMessageNullCode,
|
||||||
|
MetaMessageCheckCode,
|
||||||
|
MetaMessageShowTipCode,
|
||||||
|
MetaMessageHideTipCode
|
||||||
|
} MetaMessageCode;
|
||||||
|
|
||||||
|
struct _MetaMessageHeader
|
||||||
|
{
|
||||||
|
MetaMessageCode message_code;
|
||||||
|
int length;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* just a ping to see if we have the right
|
||||||
|
* version of UI slave.
|
||||||
|
*/
|
||||||
|
struct _MetaMessageCheck
|
||||||
|
{
|
||||||
|
MetaMessageHeader header;
|
||||||
|
|
||||||
|
/* it's OK if the max sizes aren't large enough in all cases, these
|
||||||
|
* are just paranoia checks
|
||||||
|
*/
|
||||||
|
char metacity_version[META_MESSAGE_MAX_VERSION_LEN + 1];
|
||||||
|
char host_alias[META_MESSAGE_MAX_HOST_ALIAS_LEN + 1];
|
||||||
|
int messages_version;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _MetaMessageShowTip
|
||||||
|
{
|
||||||
|
MetaMessageHeader header;
|
||||||
|
int root_x;
|
||||||
|
int root_y;
|
||||||
|
/* Then a nul-terminated string follows */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _MetaMessageHideTip
|
||||||
|
{
|
||||||
|
MetaMessageHeader header;
|
||||||
|
/* just hides the current tip */
|
||||||
|
};
|
||||||
|
|
||||||
|
union _MetaMessage
|
||||||
|
{
|
||||||
|
MetaMessageHeader header;
|
||||||
|
MetaMessageCheck check;
|
||||||
|
MetaMessageShowTip show_tip;
|
||||||
|
MetaMessageShowTip hide_tip;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Slave-side message send/read code */
|
||||||
|
|
||||||
|
void meta_message_send_check (void);
|
||||||
|
|
||||||
|
#endif
|
@ -54,6 +54,7 @@ void meta_fatal (const char *format,
|
|||||||
...) G_GNUC_PRINTF (1, 2);
|
...) G_GNUC_PRINTF (1, 2);
|
||||||
|
|
||||||
/* FIXME */
|
/* FIXME */
|
||||||
|
#include <config.h>
|
||||||
#define _(x) x
|
#define _(x) x
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
310
src/window.c
310
src/window.c
@ -34,13 +34,11 @@ 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 gboolean process_configure_request (MetaWindow *window,
|
static gboolean process_configure_request (MetaWindow *window,
|
||||||
XConfigureRequestEvent *event);
|
int x, int y, int width, int height,
|
||||||
|
int border_width);
|
||||||
static gboolean process_property_notify (MetaWindow *window,
|
static gboolean process_property_notify (MetaWindow *window,
|
||||||
XPropertyEvent *event);
|
XPropertyEvent *event);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
MetaWindow*
|
MetaWindow*
|
||||||
meta_window_new (MetaDisplay *display, Window xwindow)
|
meta_window_new (MetaDisplay *display, Window xwindow)
|
||||||
{
|
{
|
||||||
@ -57,9 +55,7 @@ meta_window_new (MetaDisplay *display, Window xwindow)
|
|||||||
xwindow, &attrs) == Success &&
|
xwindow, &attrs) == Success &&
|
||||||
attrs.override_redirect)
|
attrs.override_redirect)
|
||||||
{
|
{
|
||||||
/* Oops. Probably attempted to manage override redirect window
|
meta_verbose ("Deciding not to manage override_redirect window 0x%lx\n", xwindow);
|
||||||
* in initial screen_manage_all_windows() call.
|
|
||||||
*/
|
|
||||||
meta_error_trap_pop (display);
|
meta_error_trap_pop (display);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -67,7 +63,7 @@ meta_window_new (MetaDisplay *display, Window xwindow)
|
|||||||
XAddToSaveSet (display->xdisplay, xwindow);
|
XAddToSaveSet (display->xdisplay, xwindow);
|
||||||
|
|
||||||
XSelectInput (display->xdisplay, xwindow,
|
XSelectInput (display->xdisplay, xwindow,
|
||||||
StructureNotifyMask);
|
PropertyChangeMask);
|
||||||
|
|
||||||
if (meta_error_trap_pop (display) != Success)
|
if (meta_error_trap_pop (display) != Success)
|
||||||
{
|
{
|
||||||
@ -105,6 +101,12 @@ meta_window_new (MetaDisplay *display, Window xwindow)
|
|||||||
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;
|
||||||
|
|
||||||
|
window->size_hints.x = attrs.x;
|
||||||
|
window->size_hints.y = attrs.y;
|
||||||
|
window->size_hints.width = attrs.width;
|
||||||
|
window->size_hints.height = attrs.height;
|
||||||
|
|
||||||
window->depth = attrs.depth;
|
window->depth = attrs.depth;
|
||||||
window->xvisual = attrs.visual;
|
window->xvisual = attrs.visual;
|
||||||
|
|
||||||
@ -113,13 +115,16 @@ 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;
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
window->frame = NULL;
|
meta_window_resize (window, window->size_hints.width, window->size_hints.height);
|
||||||
|
|
||||||
meta_window_ensure_frame (window);
|
meta_window_ensure_frame (window);
|
||||||
|
|
||||||
return window;
|
return window;
|
||||||
@ -132,10 +137,10 @@ meta_window_free (MetaWindow *window)
|
|||||||
|
|
||||||
meta_display_unregister_x_window (window->display, window->xwindow);
|
meta_display_unregister_x_window (window->display, window->xwindow);
|
||||||
|
|
||||||
g_free (window->title);
|
|
||||||
|
|
||||||
meta_window_destroy_frame (window);
|
meta_window_destroy_frame (window);
|
||||||
|
|
||||||
|
g_free (window->title);
|
||||||
|
g_free (window->desc);
|
||||||
g_free (window);
|
g_free (window);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -159,13 +164,56 @@ meta_window_hide (MetaWindow *window)
|
|||||||
window->iconic = TRUE;
|
window->iconic = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_window_resize (MetaWindow *window,
|
||||||
|
int w,
|
||||||
|
int h)
|
||||||
|
{
|
||||||
|
meta_verbose ("Resizing %s to %d x %d\n", window->desc, w, h);
|
||||||
|
constrain_size (window, w, h, &w, &h);
|
||||||
|
meta_verbose ("Constrained resize of %s to %d x %d\n", window->desc, w, h);
|
||||||
|
|
||||||
|
if (w != window->rect.width ||
|
||||||
|
h != window->rect.height)
|
||||||
|
{
|
||||||
|
meta_error_trap_push (window->display);
|
||||||
|
XResizeWindow (window->display->xdisplay,
|
||||||
|
window->xwindow,
|
||||||
|
w, h);
|
||||||
|
meta_error_trap_pop (window->display);
|
||||||
|
window->rect.width = w;
|
||||||
|
window->rect.height = h;
|
||||||
|
|
||||||
|
if (window->frame)
|
||||||
|
meta_frame_queue_recalc (window->frame);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
meta_window_configure_request (MetaWindow *window,
|
||||||
|
XEvent *event)
|
||||||
|
{
|
||||||
|
return process_configure_request (window,
|
||||||
|
event->xconfigurerequest.x,
|
||||||
|
event->xconfigurerequest.y,
|
||||||
|
event->xconfigurerequest.width,
|
||||||
|
event->xconfigurerequest.height,
|
||||||
|
event->xconfigurerequest.border_width);
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
meta_window_property_notify (MetaWindow *window,
|
||||||
|
XEvent *event)
|
||||||
|
{
|
||||||
|
return process_property_notify (window, &event->xproperty);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
meta_window_event (MetaWindow *window,
|
meta_window_event (MetaWindow *window,
|
||||||
XEvent *event)
|
XEvent *event)
|
||||||
{
|
{
|
||||||
if (window->frame &&
|
|
||||||
event->xany.window == window->frame->xwindow)
|
|
||||||
return meta_frame_event (window->frame, event);
|
|
||||||
|
|
||||||
if (event->xany.window != window->xwindow)
|
if (event->xany.window != window->xwindow)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
@ -203,7 +251,7 @@ meta_window_event (MetaWindow *window,
|
|||||||
case CreateNotify:
|
case CreateNotify:
|
||||||
break;
|
break;
|
||||||
case DestroyNotify:
|
case DestroyNotify:
|
||||||
meta_window_free (window);
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
break;
|
break;
|
||||||
case UnmapNotify:
|
case UnmapNotify:
|
||||||
@ -218,17 +266,10 @@ meta_window_event (MetaWindow *window,
|
|||||||
case ReparentNotify:
|
case ReparentNotify:
|
||||||
break;
|
break;
|
||||||
case ConfigureNotify:
|
case ConfigureNotify:
|
||||||
if (event->xconfigure.override_redirect)
|
|
||||||
{
|
|
||||||
/* Unmanage it, override_redirect was toggled on?
|
|
||||||
* Can this happen?
|
|
||||||
*/
|
|
||||||
meta_window_free (window);
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case ConfigureRequest:
|
case ConfigureRequest:
|
||||||
return process_configure_request (window, &event->xconfigurerequest);
|
|
||||||
break;
|
break;
|
||||||
case GravityNotify:
|
case GravityNotify:
|
||||||
break;
|
break;
|
||||||
@ -239,7 +280,7 @@ meta_window_event (MetaWindow *window,
|
|||||||
case CirculateRequest:
|
case CirculateRequest:
|
||||||
break;
|
break;
|
||||||
case PropertyNotify:
|
case PropertyNotify:
|
||||||
return process_property_notify (window, &event->xproperty);
|
|
||||||
break;
|
break;
|
||||||
case SelectionClear:
|
case SelectionClear:
|
||||||
break;
|
break;
|
||||||
@ -269,24 +310,75 @@ process_property_notify (MetaWindow *window,
|
|||||||
event->atom == window->display->atom_net_wm_name)
|
event->atom == window->display->atom_net_wm_name)
|
||||||
{
|
{
|
||||||
update_title (window);
|
update_title (window);
|
||||||
|
|
||||||
|
if (window->frame)
|
||||||
|
meta_frame_queue_recalc (window->frame);
|
||||||
}
|
}
|
||||||
else if (event->atom == XA_WM_NORMAL_HINTS)
|
else if (event->atom == XA_WM_NORMAL_HINTS)
|
||||||
{
|
{
|
||||||
update_size_hints (window);
|
update_size_hints (window);
|
||||||
|
|
||||||
|
/* See if we need to constrain current size */
|
||||||
|
meta_window_resize (window, window->rect.width, window->rect.height);
|
||||||
}
|
}
|
||||||
else if (event->atom == XA_WM_PROTOCOLS)
|
else if (event->atom == window->display->atom_wm_protocols)
|
||||||
{
|
{
|
||||||
update_protocols (window);
|
update_protocols (window);
|
||||||
|
|
||||||
|
if (window->frame)
|
||||||
|
meta_frame_queue_recalc (window->frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
send_configure_notify (MetaWindow *window)
|
||||||
|
{
|
||||||
|
XEvent event;
|
||||||
|
|
||||||
|
/* from twm */
|
||||||
|
|
||||||
|
event.type = ConfigureNotify;
|
||||||
|
event.xconfigure.display = window->display->xdisplay;
|
||||||
|
event.xconfigure.event = window->xwindow;
|
||||||
|
event.xconfigure.window = window->xwindow;
|
||||||
|
event.xconfigure.x = window->rect.x - window->border_width;
|
||||||
|
event.xconfigure.y = window->rect.y - window->border_width;
|
||||||
|
if (window->frame)
|
||||||
|
{
|
||||||
|
/* Need to be in root window coordinates */
|
||||||
|
event.xconfigure.x += window->frame->rect.x;
|
||||||
|
event.xconfigure.y += window->frame->rect.y;
|
||||||
|
}
|
||||||
|
event.xconfigure.width = window->rect.width;
|
||||||
|
event.xconfigure.height = window->rect.height;
|
||||||
|
event.xconfigure.border_width = window->border_width; /* requested not actual */
|
||||||
|
event.xconfigure.above = None; /* FIXME */
|
||||||
|
event.xconfigure.override_redirect = False;
|
||||||
|
|
||||||
|
meta_verbose ("Sending synthetic configure notify to %s with x: %d y: %d w: %d h: %d\n",
|
||||||
|
window->desc,
|
||||||
|
event.xconfigure.x, event.xconfigure.y,
|
||||||
|
event.xconfigure.width, event.xconfigure.height);
|
||||||
|
|
||||||
|
meta_error_trap_push (window->display);
|
||||||
|
XSendEvent(window->display->xdisplay,
|
||||||
|
window->xwindow,
|
||||||
|
False, StructureNotifyMask, &event);
|
||||||
|
meta_error_trap_pop (window->display);
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
process_configure_request (MetaWindow *window,
|
process_configure_request (MetaWindow *window,
|
||||||
XConfigureRequestEvent *event)
|
int x, int y,
|
||||||
|
int width, int height,
|
||||||
|
int border_width)
|
||||||
{
|
{
|
||||||
/* ICCCM 4.1.5 */
|
/* ICCCM 4.1.5 */
|
||||||
|
XWindowChanges values;
|
||||||
|
unsigned int mask;
|
||||||
|
int client_x, client_y;
|
||||||
|
|
||||||
/* 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
|
||||||
@ -294,13 +386,83 @@ process_configure_request (MetaWindow *window,
|
|||||||
* because we don't believe in clients who use lame-ass
|
* because we don't believe in clients who use lame-ass
|
||||||
* X features like that.
|
* X features like that.
|
||||||
*/
|
*/
|
||||||
window->border_width = event->border_width;
|
window->border_width = border_width;
|
||||||
window->size_hints.x = event->x;
|
|
||||||
window->size_hints.y = event->y;
|
|
||||||
window->size_hints.width = event->width;
|
|
||||||
window->size_hints.height = event->height;
|
|
||||||
|
|
||||||
/* FIXME */
|
/* We're ignoring the value_mask here, since sizes
|
||||||
|
* not in the mask will be the current window geometry.
|
||||||
|
*/
|
||||||
|
|
||||||
|
window->size_hints.x = x;
|
||||||
|
window->size_hints.y = y;
|
||||||
|
window->size_hints.width = width;
|
||||||
|
window->size_hints.height = height;
|
||||||
|
|
||||||
|
constrain_size (window,
|
||||||
|
window->size_hints.width,
|
||||||
|
window->size_hints.height,
|
||||||
|
&window->size_hints.width,
|
||||||
|
&window->size_hints.height);
|
||||||
|
|
||||||
|
meta_verbose ("Constrained configure request size to %d x %d\n",
|
||||||
|
window->size_hints.width, window->size_hints.height);
|
||||||
|
|
||||||
|
if (window->frame)
|
||||||
|
{
|
||||||
|
meta_frame_child_configure_request (window->frame);
|
||||||
|
client_x = window->frame->child_x;
|
||||||
|
client_y = window->frame->child_y;
|
||||||
|
meta_verbose ("Will place client window %s inside frame at %d,%d\n",
|
||||||
|
window->desc, client_x, client_y);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
client_x = window->size_hints.x;
|
||||||
|
client_y = window->size_hints.y;
|
||||||
|
meta_verbose ("Will place client window %s at root coordinate %d,%d\n",
|
||||||
|
window->desc, client_x, client_y);
|
||||||
|
}
|
||||||
|
|
||||||
|
values.border_width = 0;
|
||||||
|
values.x = client_x;
|
||||||
|
values.y = client_y;
|
||||||
|
values.width = window->size_hints.width;
|
||||||
|
values.height = window->size_hints.height;
|
||||||
|
|
||||||
|
mask = 0;
|
||||||
|
if (window->border_width != 0)
|
||||||
|
mask |= CWBorderWidth;
|
||||||
|
if (values.x != window->rect.x)
|
||||||
|
mask |= CWX;
|
||||||
|
if (values.y != window->rect.y)
|
||||||
|
mask |= CWY;
|
||||||
|
if (values.width != window->rect.width)
|
||||||
|
mask |= CWWidth;
|
||||||
|
if (values.height != window->rect.height)
|
||||||
|
mask |= CWHeight;
|
||||||
|
|
||||||
|
window->rect.x = values.x;
|
||||||
|
window->rect.y = values.y;
|
||||||
|
window->rect.width = values.width;
|
||||||
|
window->rect.height = values.height;
|
||||||
|
|
||||||
|
meta_error_trap_push (window->display);
|
||||||
|
XConfigureWindow (window->display->xdisplay,
|
||||||
|
window->xwindow,
|
||||||
|
mask,
|
||||||
|
&values);
|
||||||
|
meta_error_trap_pop (window->display);
|
||||||
|
|
||||||
|
if (mask & (CWBorderWidth | CWWidth | CWHeight))
|
||||||
|
{
|
||||||
|
/* Resizing, no synthetic ConfigureNotify, third case in 4.1.5 */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Moving but not resizing, second case in 4.1.5, or
|
||||||
|
* have to send the ConfigureNotify, first case in 4.1.5
|
||||||
|
*/
|
||||||
|
send_configure_notify (window);
|
||||||
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@ -333,7 +495,12 @@ update_size_hints (MetaWindow *window)
|
|||||||
window->size_hints.height = h;
|
window->size_hints.height = h;
|
||||||
|
|
||||||
if (window->size_hints.flags & PBaseSize)
|
if (window->size_hints.flags & PBaseSize)
|
||||||
;
|
{
|
||||||
|
meta_verbose ("Window %s sets base size %d x %d\n",
|
||||||
|
window->desc,
|
||||||
|
window->size_hints.base_width,
|
||||||
|
window->size_hints.base_height);
|
||||||
|
}
|
||||||
else if (window->size_hints.flags & PMinSize)
|
else if (window->size_hints.flags & PMinSize)
|
||||||
{
|
{
|
||||||
window->size_hints.base_width = window->size_hints.min_width;
|
window->size_hints.base_width = window->size_hints.min_width;
|
||||||
@ -347,7 +514,12 @@ update_size_hints (MetaWindow *window)
|
|||||||
window->size_hints.flags |= PBaseSize;
|
window->size_hints.flags |= PBaseSize;
|
||||||
|
|
||||||
if (window->size_hints.flags & PMinSize)
|
if (window->size_hints.flags & PMinSize)
|
||||||
;
|
{
|
||||||
|
meta_verbose ("Window %s sets min size %d x %d\n",
|
||||||
|
window->desc,
|
||||||
|
window->size_hints.min_width,
|
||||||
|
window->size_hints.min_height);
|
||||||
|
}
|
||||||
else if (window->size_hints.flags & PBaseSize)
|
else if (window->size_hints.flags & PBaseSize)
|
||||||
{
|
{
|
||||||
window->size_hints.min_width = window->size_hints.base_width;
|
window->size_hints.min_width = window->size_hints.base_width;
|
||||||
@ -361,7 +533,12 @@ update_size_hints (MetaWindow *window)
|
|||||||
window->size_hints.flags |= PMinSize;
|
window->size_hints.flags |= PMinSize;
|
||||||
|
|
||||||
if (window->size_hints.flags & PMaxSize)
|
if (window->size_hints.flags & PMaxSize)
|
||||||
;
|
{
|
||||||
|
meta_verbose ("Window %s sets max size %d x %d\n",
|
||||||
|
window->desc,
|
||||||
|
window->size_hints.max_width,
|
||||||
|
window->size_hints.max_height);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
window->size_hints.max_width = G_MAXINT;
|
window->size_hints.max_width = G_MAXINT;
|
||||||
@ -370,7 +547,22 @@ update_size_hints (MetaWindow *window)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (window->size_hints.flags & PResizeInc)
|
if (window->size_hints.flags & PResizeInc)
|
||||||
;
|
{
|
||||||
|
meta_verbose ("Window %s sets resize width inc: %d height inc: %d\n",
|
||||||
|
window->desc,
|
||||||
|
window->size_hints.width_inc,
|
||||||
|
window->size_hints.height_inc);
|
||||||
|
if (window->size_hints.width_inc == 0)
|
||||||
|
{
|
||||||
|
window->size_hints.width_inc = 1;
|
||||||
|
meta_verbose ("Corrected 0 width_inc to 1\n");
|
||||||
|
}
|
||||||
|
if (window->size_hints.height_inc == 0)
|
||||||
|
{
|
||||||
|
window->size_hints.height_inc = 1;
|
||||||
|
meta_verbose ("Corrected 0 height_inc to 1\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
window->size_hints.width_inc = 1;
|
window->size_hints.width_inc = 1;
|
||||||
@ -380,6 +572,13 @@ update_size_hints (MetaWindow *window)
|
|||||||
|
|
||||||
if (window->size_hints.flags & PAspect)
|
if (window->size_hints.flags & PAspect)
|
||||||
{
|
{
|
||||||
|
meta_verbose ("Window %s sets min_aspect: %d/%d max_aspect: %d/%d\n",
|
||||||
|
window->desc,
|
||||||
|
window->size_hints.min_aspect.x,
|
||||||
|
window->size_hints.min_aspect.y,
|
||||||
|
window->size_hints.max_aspect.x,
|
||||||
|
window->size_hints.max_aspect.y);
|
||||||
|
|
||||||
/* don't divide by 0 */
|
/* don't divide by 0 */
|
||||||
if (window->size_hints.min_aspect.y < 1)
|
if (window->size_hints.min_aspect.y < 1)
|
||||||
window->size_hints.min_aspect.y = 1;
|
window->size_hints.min_aspect.y = 1;
|
||||||
@ -396,15 +595,17 @@ update_size_hints (MetaWindow *window)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (window->size_hints.flags & PWinGravity)
|
if (window->size_hints.flags & PWinGravity)
|
||||||
;
|
{
|
||||||
|
meta_verbose ("Window %s sets gravity %d\n",
|
||||||
|
window->desc,
|
||||||
|
window->size_hints.win_gravity);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
window->size_hints.win_gravity = NorthWestGravity;
|
window->size_hints.win_gravity = NorthWestGravity;
|
||||||
window->size_hints.flags |= PWinGravity;
|
window->size_hints.flags |= PWinGravity;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME constrain the window to these hints */
|
|
||||||
|
|
||||||
return meta_error_trap_pop (window->display);
|
return meta_error_trap_pop (window->display);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -487,30 +688,36 @@ update_title (MetaWindow *window)
|
|||||||
static int
|
static int
|
||||||
update_protocols (MetaWindow *window)
|
update_protocols (MetaWindow *window)
|
||||||
{
|
{
|
||||||
Atom *protocols;
|
Atom *protocols = NULL;
|
||||||
int n_protocols;
|
int n_protocols = 0;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
meta_error_trap_push (window->display);
|
|
||||||
XGetWMProtocols (window->display->xdisplay,
|
|
||||||
window->xwindow,
|
|
||||||
&protocols,
|
|
||||||
&n_protocols);
|
|
||||||
|
|
||||||
window->take_focus = FALSE;
|
window->take_focus = FALSE;
|
||||||
window->delete_window = FALSE;
|
window->delete_window = FALSE;
|
||||||
|
|
||||||
|
meta_error_trap_push (window->display);
|
||||||
|
|
||||||
|
if (XGetWMProtocols (window->display->xdisplay,
|
||||||
|
window->xwindow,
|
||||||
|
&protocols,
|
||||||
|
&n_protocols) == Success)
|
||||||
|
{
|
||||||
i = 0;
|
i = 0;
|
||||||
while (i < n_protocols)
|
while (i < n_protocols)
|
||||||
{
|
{
|
||||||
if (protocols[i] == _XA_WM_TAKE_FOCUS)
|
if (protocols[i] == window->display->atom_wm_take_focus)
|
||||||
window->takes_focus = TRUE;
|
window->take_focus = TRUE;
|
||||||
else if (protocols[i] == _XA_WM_DELETE_WINDOW)
|
else if (protocols[i] == window->display->atom_wm_delete_window)
|
||||||
window->delete_window = TRUE;
|
window->delete_window = TRUE;
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (protocols)
|
if (protocols)
|
||||||
XFree (protocols);
|
XFree (protocols);
|
||||||
|
}
|
||||||
|
|
||||||
|
meta_verbose ("Window %s has take_focus = %d delete_window = %d\n",
|
||||||
|
window->desc, window->take_focus, window->delete_window);
|
||||||
|
|
||||||
return meta_error_trap_pop (window->display);
|
return meta_error_trap_pop (window->display);
|
||||||
}
|
}
|
||||||
@ -591,3 +798,4 @@ constrain_size (MetaWindow *window,
|
|||||||
*new_width = width;
|
*new_width = width;
|
||||||
*new_height = height;
|
*new_height = height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,10 +56,17 @@ MetaWindow* meta_window_new (MetaDisplay *display,
|
|||||||
void meta_window_free (MetaWindow *window);
|
void meta_window_free (MetaWindow *window);
|
||||||
void meta_window_show (MetaWindow *window);
|
void meta_window_show (MetaWindow *window);
|
||||||
void meta_window_hide (MetaWindow *window);
|
void meta_window_hide (MetaWindow *window);
|
||||||
|
void meta_window_resize (MetaWindow *window,
|
||||||
|
int w,
|
||||||
|
int h);
|
||||||
|
|
||||||
gboolean meta_window_event (MetaWindow *window,
|
gboolean meta_window_configure_request (MetaWindow *window,
|
||||||
|
XEvent *event);
|
||||||
|
gboolean meta_window_property_notify (MetaWindow *window,
|
||||||
XEvent *event);
|
XEvent *event);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user