diff --git a/src/common.h b/src/common.h new file mode 100644 index 000000000..920856901 --- /dev/null +++ b/src/common.h @@ -0,0 +1,41 @@ +/* Metacity common types shared by core.h and ui.h */ + +/* + * 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_COMMON_H +#define META_COMMON_H + +/* Don't include GTK or core headers here */ +#include + +typedef enum +{ + META_FRAME_ALLOWS_DELETE = 1 << 0, + META_FRAME_ALLOWS_MENU = 1 << 1, + META_FRAME_ALLOWS_MINIMIZE = 1 << 2, + META_FRAME_ALLOWS_MAXIMIZE = 1 << 3, + META_FRAME_ALLOWS_RESIZE = 1 << 4, + META_FRAME_TRANSIENT = 1 << 5, + META_FRAME_HAS_FOCUS = 1 << 6, + META_FRAME_SHADED = 1 << 7, + META_FRAME_STUCK = 1 << 8 +} MetaFrameFlags; + +#endif diff --git a/src/core.c b/src/core.c index 0c935d9ab..8d07ba2bb 100644 --- a/src/core.c +++ b/src/core.c @@ -20,4 +20,42 @@ */ #include "core.h" +#include "display.h" +void +meta_core_get_frame_size (Display *xdisplay, + Window frame_xwindow, + int *width, + int *height) +{ + MetaDisplay *display; + MetaWindow *window; + + display = meta_display_for_x_display (xdisplay); + window = meta_display_lookup_x_window (display, frame_xwindow); + + if (window == NULL || window->frame == NULL) + meta_bug ("No such frame window 0x%lx!\n", frame_xwindow); + + if (width) + *width = window->frame->rect.width; + if (height) + *height = window->frame->rect.height; +} + +void +meta_core_get_frame_flags (Display *xdisplay, + Window frame_xwindow, + MetaFrameFlags flags) +{ + MetaDisplay *display; + MetaWindow *window; + + display = meta_display_for_x_display (xdisplay); + window = meta_display_lookup_x_window (display, frame_xwindow); + + if (window == NULL || window->frame == NULL) + meta_bug ("No such frame window 0x%lx!\n", frame_xwindow); + + return meta_frame_get_flags (window->frame); +} diff --git a/src/core.h b/src/core.h index f49372f9d..124a1edf8 100644 --- a/src/core.h +++ b/src/core.h @@ -26,6 +26,15 @@ #include #include #include "frames.h" +#include "common.h" +void meta_core_get_frame_size (Display *xdisplay, + Window frame_xwindow, + int *width, + int *height); + +void meta_core_get_frame_flags (Display *xdisplay, + Window frame_xwindow, + MetaFrameFlags flags); #endif diff --git a/src/display.h b/src/display.h index eaf615bbb..8a2924c24 100644 --- a/src/display.h +++ b/src/display.h @@ -24,7 +24,6 @@ #include #include -#include #include "eventqueue.h" typedef struct _MetaDisplay MetaDisplay; diff --git a/src/frame.c b/src/frame.c index f8efb9f91..02c9332d5 100644 --- a/src/frame.c +++ b/src/frame.c @@ -22,165 +22,6 @@ #include "frame.h" #include "errors.h" #include "uislave.h" -#include "colors.h" - -struct _MetaFrameActionGrab -{ - MetaFrameAction action; - /* initial mouse position for drags */ - 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; -}; - -/* This lacks ButtonReleaseMask to avoid the auto-grab - * since it breaks our popup menu - */ -#define EVENT_MASK (SubstructureRedirectMask | \ - StructureNotifyMask | SubstructureNotifyMask | \ - ExposureMask | \ - ButtonPressMask | ButtonReleaseMask | \ - PointerMotionMask | PointerMotionHintMask | \ - EnterWindowMask | LeaveWindowMask) - -static void clear_tip (MetaFrame *frame); - -static guint draw_handler = 0; -static GSList *draw_pending = NULL; - -static void -meta_frame_init_info (MetaFrame *frame, - MetaFrameInfo *info) -{ - info->flags = - META_FRAME_ALLOWS_MENU | META_FRAME_ALLOWS_RESIZE; - - if (frame->window->has_close_func) - info->flags |= META_FRAME_ALLOWS_DELETE; - - if (frame->window->type == META_WINDOW_NORMAL) - info->flags |= (META_FRAME_ALLOWS_ICONIFY | META_FRAME_ALLOWS_MAXIMIZE); - - if (!frame->window->has_maximize_func) - info->flags &= ~META_FRAME_ALLOWS_MAXIMIZE; - - if (!frame->window->has_minimize_func) - info->flags &= ~META_FRAME_ALLOWS_ICONIFY; - - if (frame->window->has_focus) - info->flags |= META_FRAME_HAS_FOCUS; - - if (frame->window->shaded) - info->flags |= META_FRAME_SHADED; - - if (frame->window->on_all_workspaces) - info->flags |= META_FRAME_STUCK; - - info->drawable = None; - info->xoffset = 0; - info->yoffset = 0; - info->display = frame->window->display->xdisplay; - info->screen = frame->window->screen->xscreen; - info->visual = frame->window->xvisual; - info->depth = frame->window->depth; - info->title = frame->window->title; - info->width = frame->rect.width; - info->height = frame->rect.height; - info->colors = &(frame->window->screen->colors); - info->current_control = frame->current_control; - if (frame->grab) - info->current_control_state = META_STATE_ACTIVE; - else - info->current_control_state = META_STATE_PRELIGHT; -} - -void -meta_frame_calc_geometry (MetaFrame *frame, - int child_width, int child_height, - MetaFrameGeometry *geomp) -{ - MetaFrameInfo info; - MetaFrameGeometry geom; - MetaWindow *window; - - /* Remember this is called from the constructor - * pre-X-window-creation. - */ - - window = frame->window; - - /* frame->rect isn't useful yet */ - - meta_frame_init_info (frame, &info); - - /* these were from frame->rect so fix them up */ - info.width = child_width; - if (window->shaded) - info.height = 0; - else - info.height = child_height; - - if (!frame->theme_acquired) - { - frame->theme_data = window->screen->engine->acquire_frame (&info); - frame->theme_acquired = TRUE; - } - - geom.left_width = 0; - geom.right_width = 0; - geom.top_height = 0; - geom.bottom_height = 0; - geom.background_pixel = - meta_screen_get_x_pixel (frame->window->screen, - &frame->window->screen->colors.bg[META_STATE_NORMAL]); - - geom.shape_mask = None; - - window->screen->engine->fill_frame_geometry (&info, &geom, - frame->theme_data); - - *geomp = geom; -} - -static void -set_background_none (MetaFrame *frame) -{ - XSetWindowAttributes attrs; - - attrs.background_pixmap = None; - XChangeWindowAttributes (frame->window->display->xdisplay, - frame->xwindow, - CWBackPixmap, - &attrs); - -#if 0 - 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); -#endif -} - -static void -set_background_color (MetaFrame *frame) -{ - XSetWindowAttributes attrs; - - attrs.background_pixel = frame->bg_pixel; - XChangeWindowAttributes (frame->window->display->xdisplay, - frame->xwindow, - CWBackPixel, - &attrs); -} void meta_window_ensure_frame (MetaWindow *window) @@ -197,24 +38,18 @@ meta_window_ensure_frame (MetaWindow *window) frame->window = window; frame->xwindow = None; - frame->theme_acquired = FALSE; - frame->grab = NULL; - frame->current_control = META_FRAME_CONTROL_NONE; - frame->tooltip_timeout = 0; frame->rect = window->rect; frame->child_x = 0; frame->child_y = 0; frame->bottom_height = 0; frame->right_width = 0; - frame->bg_pixel = 0; frame->mapped = FALSE; - - frame->edges_exposed = FALSE; - frame->title_exposed = FALSE; - attrs.event_mask = EVENT_MASK; + attrs.event_mask = SubstructureRedirectMask | + StructureNotifyMask | SubstructureNotifyMask | + EnterWindowMask | LeaveWindowMask; frame->xwindow = XCreateWindow (window->display->xdisplay, window->screen->xroot, @@ -229,6 +64,9 @@ meta_window_ensure_frame (MetaWindow *window) CWEventMask, &attrs); + /* So our UI can find the window ID */ + XFlush (window->display->xdisplay); + meta_verbose ("Frame for %s is 0x%lx\n", frame->window->desc, frame->xwindow); meta_display_register_x_window (window->display, &frame->xwindow, window); @@ -254,6 +92,8 @@ meta_window_ensure_frame (MetaWindow *window) window->rect.x, window->rect.y); meta_error_trap_pop (window->display); + + meta_ui_add_frame (window->screen->ui, frame->xwindow); /* stick frame to the window */ window->frame = frame; @@ -270,19 +110,7 @@ meta_window_destroy_frame (MetaWindow *window) frame = window->frame; - if (frame->title_exposed || frame->edges_exposed) - { - draw_pending = g_slist_remove (draw_pending, frame); - } - - if (frame->tooltip_timeout) - clear_tip (frame); - - if (frame->theme_data) - { - meta_frame_init_info (frame, &info); - window->screen->engine->release_frame (&info, frame->theme_data); - } + meta_ui_remove_frame (window->screen->ui, frame->xwindow); /* Unparent the client window; it may be destroyed, * thus the error trap. @@ -315,6 +143,68 @@ meta_window_destroy_frame (MetaWindow *window) meta_window_queue_calc_showing (window); } + +MetaFrameFlags +meta_frame_get_flags (MetaFrame *frame) +{ + MetaFrameFlags flags; + + flags = + META_FRAME_ALLOWS_MENU | META_FRAME_ALLOWS_RESIZE; + + if (frame->window->has_close_func) + flags |= META_FRAME_ALLOWS_DELETE; + + if (frame->window->type == META_WINDOW_NORMAL) + flags |= (META_FRAME_ALLOWS_ICONIFY | META_FRAME_ALLOWS_MAXIMIZE); + + if (!frame->window->has_maximize_func) + flags &= ~META_FRAME_ALLOWS_MAXIMIZE; + + if (!frame->window->has_minimize_func) + flags &= ~META_FRAME_ALLOWS_MINIMIZE; + + if (frame->window->has_focus) + flags |= META_FRAME_HAS_FOCUS; + + if (frame->window->shaded) + flags |= META_FRAME_SHADED; + + if (frame->window->on_all_workspaces) + flags |= META_FRAME_STUCK; +} + +void +meta_frame_calc_geometry (MetaFrame *frame, + MetaFrameGeometry *geomp) +{ + MetaFrameGeometry geom; + MetaWindow *window; + + window = frame->window; + + meta_ui_get_frame_geometry (window->screen->ui, + frame->xwindow, + &geom.top_height, + &geom.bottom_height, + &geom.left_width, + &geom.right_width); + + *geomp = geom; +} + +static void +set_background_none (MetaFrame *frame) +{ + XSetWindowAttributes attrs; + + attrs.background_pixmap = None; + XChangeWindowAttributes (frame->window->display->xdisplay, + frame->xwindow, + CWBackPixmap, + &attrs); +} + void meta_frame_sync_to_window (MetaFrame *frame, gboolean need_move, @@ -328,7 +218,8 @@ meta_frame_sync_to_window (MetaFrame *frame, frame->bg_pixel); /* set bg to none to avoid flicker */ - set_background_none (frame); + if (need_resize) + set_background_none (frame); if (need_move && need_resize) XMoveResizeWindow (frame->window->display->xdisplay, @@ -346,396 +237,18 @@ meta_frame_sync_to_window (MetaFrame *frame, XResizeWindow (frame->window->display->xdisplay, frame->xwindow, frame->rect.width, - frame->rect.height); - - /* also syncs bg_pixel */ - set_background_color (frame); - meta_frame_queue_draw (frame); -} + frame->rect.height); -static void -meta_frame_draw_now (MetaFrame *frame, - int x, int y, int width, int height) -{ - MetaFrameInfo info; - Pixmap p; - XGCValues vals; - - if (frame->xwindow == None) - return; - - meta_frame_init_info (frame, &info); - - if (width < 0) - width = frame->rect.width; - - if (height < 0) - height = frame->rect.height; - - if (width == 0 || height == 0) - return; - - p = XCreatePixmap (frame->window->display->xdisplay, - frame->xwindow, - width, height, - frame->window->screen->visual_info.depth); - - vals.foreground = frame->bg_pixel; - XChangeGC (frame->window->display->xdisplay, - frame->window->screen->scratch_gc, - GCForeground, - &vals); - - XFillRectangle (frame->window->display->xdisplay, - p, - frame->window->screen->scratch_gc, - 0, 0, - width, height); - - info.drawable = p; - info.xoffset = - x; - info.yoffset = - y; - - frame->window->screen->engine->expose_frame (&info, - 0, 0, width, height, - frame->theme_data); - - XCopyArea (frame->window->display->xdisplay, - p, frame->xwindow, - frame->window->screen->scratch_gc, - 0, 0, - width, height, - x, y); - - XFreePixmap (frame->window->display->xdisplay, - p); - - frame->title_exposed = FALSE; - frame->edges_exposed = FALSE; -} - -static gboolean -draw_idle (gpointer data) -{ - GSList *tmp; - - tmp = draw_pending; - while (tmp != NULL) - { - int yoffset; - MetaFrame *frame; - - frame = tmp->data; - - yoffset = 0; - if (!frame->title_exposed) - yoffset += frame->child_y; - - meta_frame_draw_now (frame, 0, yoffset, - frame->rect.width, - frame->rect.height - yoffset); - tmp = tmp->next; - } - g_slist_free (draw_pending); - draw_pending = NULL; - - draw_handler = 0; - return FALSE; + if (need_resize) + meta_ui_reset_frame_bg (frame->window->screen->ui, + frame->xwindow); } void meta_frame_queue_draw (MetaFrame *frame) { - if (draw_handler == 0) - draw_handler = g_idle_add (draw_idle, NULL); - - if (!(frame->title_exposed || frame->edges_exposed)) - draw_pending = g_slist_prepend (draw_pending, frame); - - frame->title_exposed = TRUE; - frame->edges_exposed = TRUE; -} - -static void -frame_query_root_pointer (MetaFrame *frame, - int *x, int *y) -{ - Window root_return, child_return; - int root_x_return, root_y_return; - int win_x_return, win_y_return; - unsigned int mask_return; - - XQueryPointer (frame->window->display->xdisplay, - frame->xwindow, - &root_return, - &child_return, - &root_x_return, - &root_y_return, - &win_x_return, - &win_y_return, - &mask_return); - - if (x) - *x = root_x_return; - if (y) - *y = root_y_return; -} - -static void -show_tip_now (MetaFrame *frame) -{ - const char *tiptext; - - tiptext = NULL; - switch (frame->current_control) - { - case META_FRAME_CONTROL_TITLE: - break; - case META_FRAME_CONTROL_DELETE: - tiptext = _("Close Window"); - break; - case META_FRAME_CONTROL_MENU: - tiptext = _("Menu"); - break; - case META_FRAME_CONTROL_ICONIFY: - tiptext = _("Minimize Window"); - break; - case META_FRAME_CONTROL_MAXIMIZE: - tiptext = _("Maximize Window"); - break; - case META_FRAME_CONTROL_RESIZE_SE: - break; - case META_FRAME_CONTROL_RESIZE_S: - break; - case META_FRAME_CONTROL_RESIZE_SW: - break; - case META_FRAME_CONTROL_RESIZE_N: - break; - case META_FRAME_CONTROL_RESIZE_NE: - break; - case META_FRAME_CONTROL_RESIZE_NW: - break; - case META_FRAME_CONTROL_RESIZE_W: - break; - case META_FRAME_CONTROL_RESIZE_E: - break; - case META_FRAME_CONTROL_NONE: - break; - } - - if (tiptext) - { - int x, y, width, height; - MetaFrameInfo info; - - meta_frame_init_info (frame, &info); - frame->window->screen->engine->get_control_rect (&info, - frame->current_control, - &x, &y, &width, &height, - frame->theme_data); - - /* Display tip a couple pixels below control */ - meta_screen_show_tip (frame->window->screen, - frame->rect.x + x, - frame->rect.y + y + height + 2, - tiptext); - } -} - -static gboolean -tip_timeout_func (gpointer data) -{ - MetaFrame *frame; - - frame = data; - - show_tip_now (frame); - - return FALSE; -} - -#define TIP_DELAY 250 -static void -queue_tip (MetaFrame *frame) -{ - if (frame->tooltip_timeout) - g_source_remove (frame->tooltip_timeout); - - frame->tooltip_timeout = g_timeout_add (250, - tip_timeout_func, - frame); -} - -static void -clear_tip (MetaFrame *frame) -{ - if (frame->tooltip_timeout) - { - g_source_remove (frame->tooltip_timeout); - frame->tooltip_timeout = 0; - } - meta_screen_hide_tip (frame->window->screen); -} - -static MetaFrameControl -frame_get_control (MetaFrame *frame, - int x, int y) -{ - MetaFrameInfo info; - - if (x < 0 || y < 0 || - x > frame->rect.width || y > frame->rect.height) - return META_FRAME_CONTROL_NONE; - - meta_frame_init_info (frame, &info); - - return frame->window->screen->engine->get_control (&info, - x, y, - frame->theme_data); -} - -static void -update_move (MetaFrame *frame, - int x, - int y) -{ - int dx, dy; - - dx = x - frame->grab->start_root_x; - dy = y - frame->grab->start_root_y; - - frame->window->user_has_moved = TRUE; - meta_window_move (frame->window, - frame->grab->start_window_x + dx, - frame->grab->start_window_y + dy); -} - -static void -update_resize_se (MetaFrame *frame, - int x, int y) -{ - int dx, dy; - - dx = x - frame->grab->start_root_x; - dy = y - frame->grab->start_root_y; - - frame->window->user_has_resized = TRUE; - meta_window_resize (frame->window, - frame->grab->start_window_x + dx, - frame->grab->start_window_y + dy); -} - -static void -update_current_control (MetaFrame *frame, - int x_root, int y_root) -{ - MetaFrameControl old; - - if (frame->grab) - return; - - old = frame->current_control; - - frame->current_control = frame_get_control (frame, - x_root - frame->rect.x, - y_root - frame->rect.y); - - if (old != frame->current_control) - { - meta_frame_queue_draw (frame); - - if (frame->current_control == META_FRAME_CONTROL_NONE) - clear_tip (frame); - else - queue_tip (frame); - } -} - -static void -grab_action (MetaFrame *frame, - MetaFrameAction action, - Time time) -{ - meta_verbose ("Grabbing action %d\n", action); - - frame->grab = g_new0 (MetaFrameActionGrab, 1); - - if (XGrabPointer (frame->window->display->xdisplay, - frame->xwindow, - False, - ButtonPressMask | ButtonReleaseMask | - PointerMotionMask | PointerMotionHintMask, - GrabModeAsync, GrabModeAsync, - None, - None, - time) != GrabSuccess) - meta_warning ("Grab for frame action failed\n"); - - frame->grab->action = action; - - /* display ACTIVE state */ - meta_frame_queue_draw (frame); - - clear_tip (frame); -} - -static void -ungrab_action (MetaFrame *frame, - Time time) -{ - int x, y; - - meta_verbose ("Ungrabbing action %d\n", frame->grab->action); - - XUngrabPointer (frame->window->display->xdisplay, - time); - - g_free (frame->grab); - frame->grab = NULL; - - frame_query_root_pointer (frame, &x, &y); - update_current_control (frame, x, y); - - /* undisplay ACTIVE state */ - meta_frame_queue_draw (frame); - - queue_tip (frame); -} - -static void -get_menu_items (MetaFrame *frame, - MetaFrameInfo *info, - MetaMessageWindowMenuOps *ops, - MetaMessageWindowMenuOps *insensitive) -{ - *ops = 0; - *insensitive = 0; - - if (info->flags & META_FRAME_CONTROL_MAXIMIZE) - { - if (frame->window->maximized) - *ops |= META_MESSAGE_MENU_UNMAXIMIZE; - else - *ops |= META_MESSAGE_MENU_MAXIMIZE; - } - - if (frame->window->shaded) - *ops |= META_MESSAGE_MENU_UNSHADE; - else - *ops |= META_MESSAGE_MENU_SHADE; - - if (frame->window->on_all_workspaces) - *ops |= META_MESSAGE_MENU_UNSTICK; - else - *ops |= META_MESSAGE_MENU_STICK; - - *ops |= (META_MESSAGE_MENU_DELETE | META_MESSAGE_MENU_WORKSPACES | META_MESSAGE_MENU_MINIMIZE); - - if (!(info->flags & META_FRAME_CONTROL_ICONIFY)) - *insensitive |= META_MESSAGE_MENU_MINIMIZE; - - if (!(info->flags & META_FRAME_CONTROL_DELETE)) - *insensitive |= META_MESSAGE_MENU_DELETE; + meta_ui_queue_frame_draw (frame->window->screen->ui, + frame->xwindow); } gboolean @@ -749,204 +262,10 @@ meta_frame_event (MetaFrame *frame, case KeyRelease: break; case ButtonPress: - /* you can use button 2 to move a window without raising it */ - if (event->xbutton.button == 1) - meta_window_raise (frame->window); - - update_current_control (frame, - event->xbutton.x_root, - event->xbutton.y_root); - - if (frame->grab == NULL) - { - MetaFrameControl control; - control = frame->current_control; - - if (control == META_FRAME_CONTROL_TITLE && - event->xbutton.button == 1 && - meta_display_is_double_click (frame->window->display)) - { - meta_verbose ("Double click on title\n"); - - /* FIXME this catches double click that starts elsewhere - * with the second click on title, maybe no one will - * ever notice - */ - - if (frame->window->shaded) - meta_window_unshade (frame->window); - else - meta_window_shade (frame->window); - } - else if (((control == META_FRAME_CONTROL_TITLE || - control == META_FRAME_CONTROL_NONE) && - event->xbutton.button == 1) || - event->xbutton.button == 2) - { - meta_verbose ("Begin move on %s\n", - frame->window->desc); - grab_action (frame, META_FRAME_ACTION_MOVING, - event->xbutton.time); - frame->grab->start_root_x = event->xbutton.x_root; - frame->grab->start_root_y = event->xbutton.y_root; - /* pos of client in root coords */ - frame->grab->start_window_x = - frame->rect.x + frame->window->rect.x; - frame->grab->start_window_y = - frame->rect.y + frame->window->rect.y; - frame->grab->start_button = event->xbutton.button; - } - else if (control == META_FRAME_CONTROL_DELETE && - event->xbutton.button == 1) - { - meta_verbose ("Close control clicked on %s\n", - frame->window->desc); - grab_action (frame, META_FRAME_ACTION_DELETING, - event->xbutton.time); - frame->grab->start_button = event->xbutton.button; - } - else if (control == META_FRAME_CONTROL_MAXIMIZE && - event->xbutton.button == 1) - { - meta_verbose ("Maximize control clicked on %s\n", - frame->window->desc); - grab_action (frame, META_FRAME_ACTION_TOGGLING_MAXIMIZE, - event->xbutton.time); - frame->grab->start_button = event->xbutton.button; - } - else if (control == META_FRAME_CONTROL_RESIZE_SE && - event->xbutton.button == 1) - { - meta_verbose ("Resize control clicked on %s\n", - frame->window->desc); - grab_action (frame, META_FRAME_ACTION_RESIZING_SE, - event->xbutton.time); - frame->grab->start_root_x = event->xbutton.x_root; - frame->grab->start_root_y = event->xbutton.y_root; - frame->grab->start_window_x = frame->window->rect.width; - frame->grab->start_window_y = frame->window->rect.height; - frame->grab->start_button = event->xbutton.button; - } - else if (control == META_FRAME_CONTROL_MENU && - event->xbutton.button == 1) - { - int x, y, width, height; - MetaFrameInfo info; - MetaMessageWindowMenuOps ops; - MetaMessageWindowMenuOps insensitive; - - meta_verbose ("Menu control clicked on %s\n", - frame->window->desc); - - meta_frame_init_info (frame, &info); - frame->window->screen->engine->get_control_rect (&info, - META_FRAME_CONTROL_MENU, - &x, &y, &width, &height, - frame->theme_data); - - /* Let the menu get a grab. The user could release button - * before the menu gets the grab, in which case the - * menu gets somewhat confused, but it's not that - * disastrous. - */ - XUngrabPointer (frame->window->display->xdisplay, - event->xbutton.time); - - get_menu_items (frame, &info, &ops, &insensitive); - - meta_ui_slave_show_window_menu (frame->window->screen->uislave, - frame->window, - frame->rect.x + x, - frame->rect.y + y + height, - event->xbutton.button, - ops, insensitive, - event->xbutton.time); - } - } break; case ButtonRelease: - if (frame->grab) - meta_debug_spew ("Here! grab %p action %d buttons %d %d\n", - frame->grab, frame->grab->action, frame->grab->start_button, event->xbutton.button); - if (frame->grab && - event->xbutton.button == frame->grab->start_button) - { - switch (frame->grab->action) - { - case META_FRAME_ACTION_MOVING: - update_move (frame, event->xbutton.x_root, event->xbutton.y_root); - ungrab_action (frame, event->xbutton.time); - update_current_control (frame, - event->xbutton.x_root, event->xbutton.y_root); - break; - - case META_FRAME_ACTION_RESIZING_SE: - update_resize_se (frame, event->xbutton.x_root, event->xbutton.y_root); - ungrab_action (frame, event->xbutton.time); - update_current_control (frame, - event->xbutton.x_root, event->xbutton.y_root); - break; - - case META_FRAME_ACTION_DELETING: - /* Must ungrab before getting "real" control position */ - ungrab_action (frame, event->xbutton.time); - update_current_control (frame, - event->xbutton.x_root, - event->xbutton.y_root); - /* delete if we're still over the button */ - if (frame->current_control == META_FRAME_CONTROL_DELETE) - meta_window_delete (frame->window, event->xbutton.time); - break; - case META_FRAME_ACTION_TOGGLING_MAXIMIZE: - /* Must ungrab before getting "real" control position */ - ungrab_action (frame, event->xbutton.time); - update_current_control (frame, - event->xbutton.x_root, - event->xbutton.y_root); - /* delete if we're still over the button */ - if (frame->current_control == META_FRAME_CONTROL_MAXIMIZE) - { - if (frame->window->maximized) - meta_window_unmaximize (frame->window); - else - meta_window_maximize (frame->window); - } - break; - default: - meta_warning ("Unhandled action in button release\n"); - break; - } - } break; case MotionNotify: - { - int x, y; - - frame_query_root_pointer (frame, &x, &y); - if (frame->grab) - { - switch (frame->grab->action) - { - case META_FRAME_ACTION_MOVING: - update_move (frame, x, y); - break; - - case META_FRAME_ACTION_RESIZING_SE: - update_resize_se (frame, x, y); - break; - - case META_FRAME_ACTION_NONE: - - break; - default: - break; - } - } - else - { - update_current_control (frame, x, y); - } - } break; case EnterNotify: /* We handle it here if a decorated window @@ -957,7 +276,6 @@ meta_frame_event (MetaFrame *frame, event->xcrossing.time); break; case LeaveNotify: - update_current_control (frame, -1, -1); break; case FocusIn: break; @@ -966,13 +284,6 @@ meta_frame_event (MetaFrame *frame, case KeymapNotify: break; case Expose: - { - gboolean title_was_exposed = frame->title_exposed; - meta_frame_queue_draw (frame); - if (!title_was_exposed && - event->xexpose.y > frame->child_y) - frame->title_exposed = FALSE; - } break; case GraphicsExpose: break; @@ -995,12 +306,8 @@ meta_frame_event (MetaFrame *frame, } break; case UnmapNotify: - if (frame->grab) - ungrab_action (frame, CurrentTime); break; case MapNotify: - if (frame->grab) - ungrab_action (frame, CurrentTime); break; case MapRequest: break; @@ -1009,13 +316,6 @@ meta_frame_event (MetaFrame *frame, case ConfigureNotify: break; case ConfigureRequest: - { - /* This is a request from the UISlave, or else a client - * that's completely out of line. We call - * meta_window_move_resize() using this information. - */ - - } break; case GravityNotify: break; diff --git a/src/frame.h b/src/frame.h index 314d1c200..642491bb5 100644 --- a/src/frame.h +++ b/src/frame.h @@ -24,16 +24,14 @@ #include "window.h" -typedef enum -{ - META_FRAME_ACTION_NONE, - META_FRAME_ACTION_MOVING, - META_FRAME_ACTION_DELETING, - META_FRAME_ACTION_TOGGLING_MAXIMIZE, - META_FRAME_ACTION_RESIZING_SE -} MetaFrameAction; - -typedef struct _MetaFrameActionGrab MetaFrameActionGrab; +struct _MetaFrameGeometry +{ + /* border sizes (space between frame and child) */ + int left_width; + int right_width; + int top_height; + int bottom_height; +}; struct _MetaFrame { @@ -47,26 +45,14 @@ struct _MetaFrame * frame, not the result of ConfigureNotify */ MetaRectangle rect; + + /* position of client, size of frame */ int child_x; int child_y; int right_width; int bottom_height; - - gpointer theme_data; - gulong bg_pixel; - MetaFrameActionGrab *grab; - - MetaFrameControl current_control; - - guint tooltip_timeout; - - guint theme_acquired : 1; guint mapped : 1; - - /* world's lamest expose compression */ - guint edges_exposed : 1; - guint title_exposed : 1; }; void meta_window_ensure_frame (MetaWindow *window); @@ -75,10 +61,10 @@ void meta_frame_queue_draw (MetaFrame *frame); gboolean meta_frame_event (MetaFrame *frame, XEvent *event); -/* These three should ONLY be called from meta_window_move_resize_internal */ +MetaFrameFlags meta_frame_get_flags (MetaFrame *frame); + +/* These should ONLY be called from meta_window_move_resize_internal */ void meta_frame_calc_geometry (MetaFrame *frame, - int child_width, - int child_height, MetaFrameGeometry *geomp); void meta_frame_sync_to_window (MetaFrame *frame, gboolean need_move, diff --git a/src/frames.c b/src/frames.c index 7fb0130ad..dac569836 100644 --- a/src/frames.c +++ b/src/frames.c @@ -21,15 +21,35 @@ #include "frames.h" + +struct _MetaFrameActionGrab +{ + MetaFrameAction action; + /* initial mouse position for drags */ + 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; +}; + + +/* This lacks ButtonReleaseMask to avoid the auto-grab + * since it breaks our popup menu + */ +#define EVENT_MASK (SubstructureRedirectMask | \ + StructureNotifyMask | SubstructureNotifyMask | \ + ExposureMask | \ + ButtonPressMask | ButtonReleaseMask | \ + PointerMotionMask | PointerMotionHintMask | \ + EnterWindowMask | LeaveWindowMask) + struct _MetaFrame { Window xwindow; GdkWindow *window; PangoLayout *layout; MetaFrameFlags flags; - /* w/h of frame window */ - int width; - int height; }; struct _MetaFrameProperties @@ -130,6 +150,7 @@ gboolean meta_frames_window_state_event (GtkWidget *widget, static void meta_frames_calc_geometry (MetaFrames *frames, + MetaFrame *frame, MetaFrameGeometry *fgeom); static MetaFrame* meta_frames_lookup_window (MetaFrames *frames, @@ -251,13 +272,6 @@ meta_frames_init (MetaFrames *frames) frames->frames = g_hash_table_new (unsigned_long_hash, unsigned_long_equal); } -static void -meta_frames_destroy (GtkObject *object) -{ - - GTK_OBJECT_CLASS (parent_class)->destroy (object); -} - static void listify_func (gpointer key, gpointer value, gpointer data) { @@ -268,14 +282,14 @@ listify_func (gpointer key, gpointer value, gpointer data) } static void -meta_frames_finalize (GObject *object) +meta_frames_destroy (GtkObject *object) { - MetaFrames *frames; GSList *winlist; GSList *tmp; + MetaFrames *frames; frames = META_FRAMES (object); - + winlist = NULL; g_hash_table_foreach (frames->frames, listify_func, @@ -295,6 +309,16 @@ meta_frames_finalize (GObject *object) } g_slist_free (winlist); + GTK_OBJECT_CLASS (parent_class)->destroy (object); +} + +static void +meta_frames_finalize (GObject *object) +{ + MetaFrames *frames; + + frames = META_FRAMES (object); + g_assert (g_hash_table_size (frames->frames) == 0); g_hash_table_destroy (frames->frames); @@ -410,9 +434,13 @@ meta_frames_calc_geometry (MetaFrames *frames, gboolean shaded; MetaFrameProperties props; int buttons_height, title_height, spacer_height; + int width, height; props = *(frames->props); + meta_core_get_frame_size (gdk_display, frame->xwindow, + &width, &height); + buttons_height = props.button_height + props.button_border.top + props.button_border.bottom; title_height = frames->text_height + @@ -431,7 +459,7 @@ meta_frames_calc_geometry (MetaFrames *frames, else fgeom->bottom_height = props.bottom_height; - x = frame->width - fgeom->button_inset; + x = width - fgeom->button_inset; /* center buttons */ button_y = (fgeom->top_height - @@ -570,17 +598,13 @@ meta_frames_manage_window (MetaFrames *frames, g_return_if_fail (GDK_IS_WINDOW (window)); frame = g_new (MetaFrame, 1); - - gdk_error_trap_push (); frame->window = gdk_window_foreign_new (xwindow); if (frame->window == NULL) { - gdk_flush (); - gdk_error_trap_pop (); g_free (frame); - meta_ui_warning ("Frame 0x%lx disappeared as we managed it\n", xwindow); + meta_bug ("Frame 0x%lx doesn't exist\n", xwindow); return; } @@ -594,9 +618,6 @@ meta_frames_manage_window (MetaFrames *frames, GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK); - gdk_drawable_get_size (GDK_DRAWABLE (frame->window), - &frame->width, &frame->height); - /* This shouldn't be required if we don't select for button * press in frame.c? */ @@ -607,15 +628,8 @@ meta_frames_manage_window (MetaFrames *frames, GrabModeAsync, GrabModeAsync, False, None); - gdk_flush (); - if (gdk_error_trap_pop ()) - { - g_object_unref (G_OBJECT (frame->window)); - g_free (frame); - meta_ui_warning ("Errors managing frame 0x%lx\n", xwindow); - return; - } - + XFlush (gdk_display); + frame->xwindow = xwindow; frame->layout = NULL; frame->flags = 0; @@ -657,6 +671,102 @@ meta_frames_lookup_window (MetaFrames *frames, return frame; } +void +meta_frames_get_geometry (MetaFrames *frames, + Window xwindow, + int *top_height, int *bottom_height, + int *left_width, int *right_width) +{ + MetaFrameGeometry fgeom; + + MetaFrame *frame; + + frame = meta_frames_lookup_window (frames, xwindow); + + if (frame == NULL) + meta_bug ("No such frame 0x%lx\n", xwindow); + + meta_frames_calc_geometry (frames, frame, &fgeom); + + if (top_height) + *top_height = fgeom.top_height; + if (bottom_height) + *bottom_height = fgeom.bottom_height; + if (left_width) + *left_width = fgeom.left_width; + if (right_width) + *right_width = fgeom.right_width; +} + +void +meta_frames_reset_bg (MetaFrames *frames, + Window xwindow) +{ + GtkWidget *widget; + MetaFrame *frame; + + widget = GTK_WIDGET (frames); + + frame = meta_frames_lookup_window (frames, xwindow); + + gtk_style_set_background (widget->style, frame->window, GTK_STATE_NORMAL); +} + +void +meta_frames_set_flags (MetaFrames *frames, + Window xwindow, + MetaFrameFlags flags) +{ + GtkWidget *widget; + MetaFrame *frame; + + widget = GTK_WIDGET (frames); + + frame = meta_frames_lookup_window (frames, xwindow); + + if (frame->flags == flags) + return; + + frame->flags = flags; + + gdk_window_invalidate_rect (frame->window, NULL, FALSE); +} + +void +meta_frames_queue_draw (MetaFrames *frames, + Window xwindow) +{ + GtkWidget *widget; + MetaFrame *frame; + + widget = GTK_WIDGET (frames); + + frame = meta_frames_lookup_window (frames, xwindow); + + gdk_window_invalidate_rect (frame->window, NULL, FALSE); +} + +void +meta_frames_set_title (MetaFrames *frames, + Window xwindow, + const char *title) +{ + GtkWidget *widget; + MetaFrame *frame; + + widget = GTK_WIDGET (frames); + + frame = meta_frames_lookup_window (frames, xwindow); + + if (frame->layout == NULL) + frame->layout = gtk_widget_create_pango_layout (widget, + title); + else + pango_layout_set_text (frame->layout, title, -1); + + gdk_window_invalidate_rect (frame->window, NULL, FALSE); +} + gboolean meta_frames_button_press_event (GtkWidget *widget, GdkEventButton *event) @@ -929,3 +1039,596 @@ meta_frames_window_state_event (GtkWidget *widget, return TRUE; } + +#if 0 + +static void +frame_query_root_pointer (MetaFrame *frame, + int *x, int *y) +{ + Window root_return, child_return; + int root_x_return, root_y_return; + int win_x_return, win_y_return; + unsigned int mask_return; + + XQueryPointer (frame->window->display->xdisplay, + frame->xwindow, + &root_return, + &child_return, + &root_x_return, + &root_y_return, + &win_x_return, + &win_y_return, + &mask_return); + + if (x) + *x = root_x_return; + if (y) + *y = root_y_return; +} + +static void +show_tip_now (MetaFrame *frame) +{ + const char *tiptext; + + tiptext = NULL; + switch (frame->current_control) + { + case META_FRAME_CONTROL_TITLE: + break; + case META_FRAME_CONTROL_DELETE: + tiptext = _("Close Window"); + break; + case META_FRAME_CONTROL_MENU: + tiptext = _("Menu"); + break; + case META_FRAME_CONTROL_ICONIFY: + tiptext = _("Minimize Window"); + break; + case META_FRAME_CONTROL_MAXIMIZE: + tiptext = _("Maximize Window"); + break; + case META_FRAME_CONTROL_RESIZE_SE: + break; + case META_FRAME_CONTROL_RESIZE_S: + break; + case META_FRAME_CONTROL_RESIZE_SW: + break; + case META_FRAME_CONTROL_RESIZE_N: + break; + case META_FRAME_CONTROL_RESIZE_NE: + break; + case META_FRAME_CONTROL_RESIZE_NW: + break; + case META_FRAME_CONTROL_RESIZE_W: + break; + case META_FRAME_CONTROL_RESIZE_E: + break; + case META_FRAME_CONTROL_NONE: + break; + } + + if (tiptext) + { + int x, y, width, height; + MetaFrameInfo info; + + meta_frame_init_info (frame, &info); + frame->window->screen->engine->get_control_rect (&info, + frame->current_control, + &x, &y, &width, &height, + frame->theme_data); + + /* Display tip a couple pixels below control */ + meta_screen_show_tip (frame->window->screen, + frame->rect.x + x, + frame->rect.y + y + height + 2, + tiptext); + } +} + +static gboolean +tip_timeout_func (gpointer data) +{ + MetaFrame *frame; + + frame = data; + + show_tip_now (frame); + + return FALSE; +} + +#define TIP_DELAY 250 +static void +queue_tip (MetaFrame *frame) +{ + if (frame->tooltip_timeout) + g_source_remove (frame->tooltip_timeout); + + frame->tooltip_timeout = g_timeout_add (250, + tip_timeout_func, + frame); +} + +static void +clear_tip (MetaFrame *frame) +{ + if (frame->tooltip_timeout) + { + g_source_remove (frame->tooltip_timeout); + frame->tooltip_timeout = 0; + } + meta_screen_hide_tip (frame->window->screen); +} + +static MetaFrameControl +frame_get_control (MetaFrame *frame, + int x, int y) +{ + MetaFrameInfo info; + + if (x < 0 || y < 0 || + x > frame->rect.width || y > frame->rect.height) + return META_FRAME_CONTROL_NONE; + + meta_frame_init_info (frame, &info); + + return frame->window->screen->engine->get_control (&info, + x, y, + frame->theme_data); +} + +static void +update_move (MetaFrame *frame, + int x, + int y) +{ + int dx, dy; + + dx = x - frame->grab->start_root_x; + dy = y - frame->grab->start_root_y; + + frame->window->user_has_moved = TRUE; + meta_window_move (frame->window, + frame->grab->start_window_x + dx, + frame->grab->start_window_y + dy); +} + +static void +update_resize_se (MetaFrame *frame, + int x, int y) +{ + int dx, dy; + + dx = x - frame->grab->start_root_x; + dy = y - frame->grab->start_root_y; + + frame->window->user_has_resized = TRUE; + meta_window_resize (frame->window, + frame->grab->start_window_x + dx, + frame->grab->start_window_y + dy); +} + +static void +update_current_control (MetaFrame *frame, + int x_root, int y_root) +{ + MetaFrameControl old; + + if (frame->grab) + return; + + old = frame->current_control; + + frame->current_control = frame_get_control (frame, + x_root - frame->rect.x, + y_root - frame->rect.y); + + if (old != frame->current_control) + { + meta_frame_queue_draw (frame); + + if (frame->current_control == META_FRAME_CONTROL_NONE) + clear_tip (frame); + else + queue_tip (frame); + } +} + +static void +grab_action (MetaFrame *frame, + MetaFrameAction action, + Time time) +{ + meta_verbose ("Grabbing action %d\n", action); + + frame->grab = g_new0 (MetaFrameActionGrab, 1); + + if (XGrabPointer (frame->window->display->xdisplay, + frame->xwindow, + False, + ButtonPressMask | ButtonReleaseMask | + PointerMotionMask | PointerMotionHintMask, + GrabModeAsync, GrabModeAsync, + None, + None, + time) != GrabSuccess) + meta_warning ("Grab for frame action failed\n"); + + frame->grab->action = action; + + /* display ACTIVE state */ + meta_frame_queue_draw (frame); + + clear_tip (frame); +} + +static void +ungrab_action (MetaFrame *frame, + Time time) +{ + int x, y; + + meta_verbose ("Ungrabbing action %d\n", frame->grab->action); + + XUngrabPointer (frame->window->display->xdisplay, + time); + + g_free (frame->grab); + frame->grab = NULL; + + frame_query_root_pointer (frame, &x, &y); + update_current_control (frame, x, y); + + /* undisplay ACTIVE state */ + meta_frame_queue_draw (frame); + + queue_tip (frame); +} + +static void +get_menu_items (MetaFrame *frame, + MetaFrameInfo *info, + MetaMessageWindowMenuOps *ops, + MetaMessageWindowMenuOps *insensitive) +{ + *ops = 0; + *insensitive = 0; + + if (info->flags & META_FRAME_CONTROL_MAXIMIZE) + { + if (frame->window->maximized) + *ops |= META_MESSAGE_MENU_UNMAXIMIZE; + else + *ops |= META_MESSAGE_MENU_MAXIMIZE; + } + + if (frame->window->shaded) + *ops |= META_MESSAGE_MENU_UNSHADE; + else + *ops |= META_MESSAGE_MENU_SHADE; + + if (frame->window->on_all_workspaces) + *ops |= META_MESSAGE_MENU_UNSTICK; + else + *ops |= META_MESSAGE_MENU_STICK; + + *ops |= (META_MESSAGE_MENU_DELETE | META_MESSAGE_MENU_WORKSPACES | META_MESSAGE_MENU_MINIMIZE); + + if (!(info->flags & META_FRAME_CONTROL_ICONIFY)) + *insensitive |= META_MESSAGE_MENU_MINIMIZE; + + if (!(info->flags & META_FRAME_CONTROL_DELETE)) + *insensitive |= META_MESSAGE_MENU_DELETE; +} + +gboolean +meta_frame_event (MetaFrame *frame, + XEvent *event) +{ + switch (event->type) + { + case KeyPress: + break; + case KeyRelease: + break; + case ButtonPress: + /* you can use button 2 to move a window without raising it */ + if (event->xbutton.button == 1) + meta_window_raise (frame->window); + + update_current_control (frame, + event->xbutton.x_root, + event->xbutton.y_root); + + if (frame->grab == NULL) + { + MetaFrameControl control; + control = frame->current_control; + + if (control == META_FRAME_CONTROL_TITLE && + event->xbutton.button == 1 && + meta_display_is_double_click (frame->window->display)) + { + meta_verbose ("Double click on title\n"); + + /* FIXME this catches double click that starts elsewhere + * with the second click on title, maybe no one will + * ever notice + */ + + if (frame->window->shaded) + meta_window_unshade (frame->window); + else + meta_window_shade (frame->window); + } + else if (((control == META_FRAME_CONTROL_TITLE || + control == META_FRAME_CONTROL_NONE) && + event->xbutton.button == 1) || + event->xbutton.button == 2) + { + meta_verbose ("Begin move on %s\n", + frame->window->desc); + grab_action (frame, META_FRAME_ACTION_MOVING, + event->xbutton.time); + frame->grab->start_root_x = event->xbutton.x_root; + frame->grab->start_root_y = event->xbutton.y_root; + /* pos of client in root coords */ + frame->grab->start_window_x = + frame->rect.x + frame->window->rect.x; + frame->grab->start_window_y = + frame->rect.y + frame->window->rect.y; + frame->grab->start_button = event->xbutton.button; + } + else if (control == META_FRAME_CONTROL_DELETE && + event->xbutton.button == 1) + { + meta_verbose ("Close control clicked on %s\n", + frame->window->desc); + grab_action (frame, META_FRAME_ACTION_DELETING, + event->xbutton.time); + frame->grab->start_button = event->xbutton.button; + } + else if (control == META_FRAME_CONTROL_MAXIMIZE && + event->xbutton.button == 1) + { + meta_verbose ("Maximize control clicked on %s\n", + frame->window->desc); + grab_action (frame, META_FRAME_ACTION_TOGGLING_MAXIMIZE, + event->xbutton.time); + frame->grab->start_button = event->xbutton.button; + } + else if (control == META_FRAME_CONTROL_RESIZE_SE && + event->xbutton.button == 1) + { + meta_verbose ("Resize control clicked on %s\n", + frame->window->desc); + grab_action (frame, META_FRAME_ACTION_RESIZING_SE, + event->xbutton.time); + frame->grab->start_root_x = event->xbutton.x_root; + frame->grab->start_root_y = event->xbutton.y_root; + frame->grab->start_window_x = frame->window->rect.width; + frame->grab->start_window_y = frame->window->rect.height; + frame->grab->start_button = event->xbutton.button; + } + else if (control == META_FRAME_CONTROL_MENU && + event->xbutton.button == 1) + { + int x, y, width, height; + MetaFrameInfo info; + MetaMessageWindowMenuOps ops; + MetaMessageWindowMenuOps insensitive; + + meta_verbose ("Menu control clicked on %s\n", + frame->window->desc); + + meta_frame_init_info (frame, &info); + frame->window->screen->engine->get_control_rect (&info, + META_FRAME_CONTROL_MENU, + &x, &y, &width, &height, + frame->theme_data); + + /* Let the menu get a grab. The user could release button + * before the menu gets the grab, in which case the + * menu gets somewhat confused, but it's not that + * disastrous. + */ + XUngrabPointer (frame->window->display->xdisplay, + event->xbutton.time); + + get_menu_items (frame, &info, &ops, &insensitive); + + meta_ui_slave_show_window_menu (frame->window->screen->uislave, + frame->window, + frame->rect.x + x, + frame->rect.y + y + height, + event->xbutton.button, + ops, insensitive, + event->xbutton.time); + } + } + break; + case ButtonRelease: + if (frame->grab) + meta_debug_spew ("Here! grab %p action %d buttons %d %d\n", + frame->grab, frame->grab->action, frame->grab->start_button, event->xbutton.button); + if (frame->grab && + event->xbutton.button == frame->grab->start_button) + { + switch (frame->grab->action) + { + case META_FRAME_ACTION_MOVING: + update_move (frame, event->xbutton.x_root, event->xbutton.y_root); + ungrab_action (frame, event->xbutton.time); + update_current_control (frame, + event->xbutton.x_root, event->xbutton.y_root); + break; + + case META_FRAME_ACTION_RESIZING_SE: + update_resize_se (frame, event->xbutton.x_root, event->xbutton.y_root); + ungrab_action (frame, event->xbutton.time); + update_current_control (frame, + event->xbutton.x_root, event->xbutton.y_root); + break; + + case META_FRAME_ACTION_DELETING: + /* Must ungrab before getting "real" control position */ + ungrab_action (frame, event->xbutton.time); + update_current_control (frame, + event->xbutton.x_root, + event->xbutton.y_root); + /* delete if we're still over the button */ + if (frame->current_control == META_FRAME_CONTROL_DELETE) + meta_window_delete (frame->window, event->xbutton.time); + break; + case META_FRAME_ACTION_TOGGLING_MAXIMIZE: + /* Must ungrab before getting "real" control position */ + ungrab_action (frame, event->xbutton.time); + update_current_control (frame, + event->xbutton.x_root, + event->xbutton.y_root); + /* delete if we're still over the button */ + if (frame->current_control == META_FRAME_CONTROL_MAXIMIZE) + { + if (frame->window->maximized) + meta_window_unmaximize (frame->window); + else + meta_window_maximize (frame->window); + } + break; + default: + meta_warning ("Unhandled action in button release\n"); + break; + } + } + break; + case MotionNotify: + { + int x, y; + + frame_query_root_pointer (frame, &x, &y); + if (frame->grab) + { + switch (frame->grab->action) + { + case META_FRAME_ACTION_MOVING: + update_move (frame, x, y); + break; + + case META_FRAME_ACTION_RESIZING_SE: + update_resize_se (frame, x, y); + break; + + case META_FRAME_ACTION_NONE: + + break; + default: + break; + } + } + else + { + update_current_control (frame, x, y); + } + } + break; + 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; + case LeaveNotify: + update_current_control (frame, -1, -1); + break; + case FocusIn: + break; + case FocusOut: + break; + case KeymapNotify: + break; + case Expose: + { + gboolean title_was_exposed = frame->title_exposed; + meta_frame_queue_draw (frame); + if (!title_was_exposed && + event->xexpose.y > frame->child_y) + frame->title_exposed = FALSE; + } + break; + case GraphicsExpose: + break; + case NoExpose: + break; + case VisibilityNotify: + break; + case CreateNotify: + break; + 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); + display = frame->window->display; + meta_error_trap_push (display); + meta_window_destroy_frame (frame->window); + meta_error_trap_pop (display); + return TRUE; + } + break; + case UnmapNotify: + if (frame->grab) + ungrab_action (frame, CurrentTime); + break; + case MapNotify: + if (frame->grab) + ungrab_action (frame, CurrentTime); + break; + case MapRequest: + break; + case ReparentNotify: + break; + case ConfigureNotify: + break; + case ConfigureRequest: + { + /* This is a request from the UISlave, or else a client + * that's completely out of line. We call + * meta_window_move_resize() using this information. + */ + + } + 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; + } + + return FALSE; +} +#endif diff --git a/src/frames.h b/src/frames.h index 444b8b1f5..eb42dd655 100644 --- a/src/frames.h +++ b/src/frames.h @@ -24,7 +24,25 @@ #include #include -#include "messages.h" +#include "common.h" + +typedef enum +{ + META_FRAME_CONTROL_NONE, + META_FRAME_CONTROL_TITLE, + META_FRAME_CONTROL_DELETE, + META_FRAME_CONTROL_MENU, + META_FRAME_CONTROL_MINIMIZE, + META_FRAME_CONTROL_MAXIMIZE, + META_FRAME_CONTROL_RESIZE_SE, + META_FRAME_CONTROL_RESIZE_S, + META_FRAME_CONTROL_RESIZE_SW, + META_FRAME_CONTROL_RESIZE_N, + META_FRAME_CONTROL_RESIZE_NE, + META_FRAME_CONTROL_RESIZE_NW, + META_FRAME_CONTROL_RESIZE_W, + META_FRAME_CONTROL_RESIZE_E +} MetaFrameControl; /* This is one widget that manages all the window frames * as subwindows. @@ -73,4 +91,19 @@ void meta_frames_set_title (MetaFrames *frames, Window xwindow, const char *title); +void meta_frames_get_geometry (MetaFrames *frames, + Window xwindow, + int *top_height, int *bottom_height, + int *left_width, int *right_width); + +void meta_frames_reset_bg (MetaFrames *frames, + Window xwindow); + +void meta_frames_set_flags (MetaFrames *frames, + Window xwindow, + MetaFrameFlags flags); + +void meta_frames_queue_draw (MetaFrames *frames, + Window xwindow); + #endif diff --git a/src/screen.c b/src/screen.c index f6029c50a..55715c469 100644 --- a/src/screen.c +++ b/src/screen.c @@ -23,8 +23,6 @@ #include "util.h" #include "errors.h" #include "window.h" -#include "colors.h" -#include "uislave.h" #include "frame.h" #include "workspace.h" #include "keybindings.h" @@ -35,9 +33,6 @@ #include #include -static void ui_slave_func (MetaUISlave *uislave, - MetaMessage *message, - gpointer data); static char* get_screen_name (MetaDisplay *display, int number); @@ -188,10 +183,9 @@ meta_screen_new (MetaDisplay *display, screen->xroot, 0, &vals); - - screen->uislave = meta_ui_slave_new (screen->screen_name, - ui_slave_func, - screen); + + screen->ui = meta_ui_new (screen->display, + screen->xscreen); screen->stack = meta_stack_new (screen); @@ -397,37 +391,6 @@ meta_screen_for_x_screen (Screen *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) diff --git a/src/screen.h b/src/screen.h index 24337492a..adcce4729 100644 --- a/src/screen.h +++ b/src/screen.h @@ -25,6 +25,7 @@ #include "display.h" #include "theme.h" #include +#include "ui.h" typedef void (* MetaScreenWindowFunc) (MetaScreen *screen, MetaWindow *window, gpointer user_data); @@ -37,7 +38,7 @@ struct _MetaScreen Screen *xscreen; Window xroot; MetaThemeEngine *engine; - MetaUISlave *uislave; + MetaUI *ui; MetaWorkspace *active_workspace; diff --git a/src/ui.c b/src/ui.c index 41ec45c4a..7479c79c3 100644 --- a/src/ui.c +++ b/src/ui.c @@ -20,9 +20,93 @@ */ #include "ui.h" +#include "frames.h" + +struct _MetaUI +{ + Display *xdisplay; + Screen *xscreen; + MetaFrames *frames; +}; void meta_ui_init (int *argc, char ***argv) { gtk_init (argc, argv); } + +MetaUI* +meta_ui_new (Display *xdisplay, + Screen *screen) +{ + MetaUI *ui; + + ui = g_new (MetaUI, 1); + ui->xdisplay = xdisplay; + ui->xscreen = screen; + + /* FIXME when gtk has multihead use it here */ + ui->frames = meta_frames_new (); + gtk_widget_realize (GTK_WIDGET (ui->frames)); + + return ui; +} + +void +meta_ui_free (MetaUI *ui) +{ + gtk_widget_destroy (GTK_WIDGET (ui->frames)); + + g_free (ui); +} + +void +meta_ui_get_frame_geometry (MetaUI *ui, + Window frame_xwindow, + int *top_height, int *bottom_height, + int *left_width, int *right_width) +{ + meta_frames_get_geometry (ui->frames, frame_xwindow, + top_height, bottom_height, + left_width, right_width); +} + + +void +meta_ui_add_frame (MetaUI *ui, + Window xwindow) +{ + meta_frames_manage_window (ui->frames, xwindow); +} + +void +meta_ui_remove_frame (MetaUI *ui, + Window xwindow) +{ + meta_frames_unmanage_window (ui->frames, xwindow); +} + +void +meta_ui_reset_frame_bg (MetaUI *ui, + Window xwindow) +{ + meta_frames_reset_bg (ui->frames, xwindow); +} + +void +meta_ui_set_frame_flags (MetaUI *ui, + Window xwindow, + MetaFrameFlags flags) +{ + meta_frames_set_flags (ui->frames, xwindow, flags); +} + +void +meta_ui_queue_frame_draw (MetaUI *ui, + Window xwindow) +{ + meta_frames_queue_draw (ui->frames, xwindow); +} + + + diff --git a/src/ui.h b/src/ui.h index 4e2260e37..17c843955 100644 --- a/src/ui.h +++ b/src/ui.h @@ -29,8 +29,28 @@ typedef struct _MetaUI MetaUI; void meta_ui_init (int *argc, char ***argv); -MetaUI* meta_ui_new (Display *xdisplay); +MetaUI* meta_ui_new (Display *xdisplay, + Screen *screen); void meta_ui_free (MetaUI *ui); +void meta_ui_get_frame_geometry (MetaUI *ui, + Window frame_xwindow, + int *top_height, int *bottom_height, + int *left_width, int *right_width); +void meta_ui_add_frame (MetaUI *ui, + Window xwindow); +void meta_ui_remove_frame (MetaUI *ui, + Window xwindow); + + +void meta_ui_reset_frame_bg (MetaUI *ui, + Window xwindow); + +void meta_ui_set_frame_flags (MetaUI *ui, + Window xwindow, + MetaFrameFlags flags); + +void meta_ui_queue_frame_draw (MetaUI *ui, + Window xwindow); #endif diff --git a/src/window.c b/src/window.c index 927b1f3f7..51e536609 100644 --- a/src/window.c +++ b/src/window.c @@ -802,8 +802,6 @@ meta_window_move_resize_internal (MetaWindow *window, */ if (window->frame) meta_frame_calc_geometry (window->frame, - window->rect.width, - window->rect.height, &fgeom); constrain_size (window, &fgeom, w, h, &w, &h);