summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorrhp <rhp>2001-06-06 04:47:37 +0000
committerrhp <rhp>2001-06-06 04:47:37 +0000
commit0f5fdeb1b15a84a790d14beb4488eb974c7e0cd0 (patch)
treec13a9394594ff3ec6b2115fe0d4efc43a944d508 /src
parentad6efc61b5d8c4572eac2ad586bca4e7b54d9c7c (diff)
downloadmetacity-0f5fdeb1b15a84a790d14beb4488eb974c7e0cd0.tar.gz
metacity-0f5fdeb1b15a84a790d14beb4488eb974c7e0cd0.tar.bz2
...
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am4
-rw-r--r--src/display.c68
-rw-r--r--src/display.h23
-rw-r--r--src/frame.c402
-rw-r--r--src/frame.h20
-rw-r--r--src/keybindings.c172
-rw-r--r--src/keybindings.h37
-rw-r--r--src/screen.c37
-rw-r--r--src/screen.h10
-rw-r--r--src/theme.c156
-rw-r--r--src/theme.h9
-rw-r--r--src/uislave.c12
-rw-r--r--src/uislave.h1
-rw-r--r--src/uislave/main.c4
-rw-r--r--src/window.c219
-rw-r--r--src/window.h38
-rw-r--r--src/workspace.c141
-rw-r--r--src/workspace.h48
18 files changed, 1238 insertions, 163 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 9f4f4f2..065efc6 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -49,6 +49,8 @@ metacity_SOURCES= \
eventqueue.h \
frame.c \
frame.h \
+ keybindings.c \
+ keybindings.h \
main.c \
main.h \
screen.c \
@@ -61,6 +63,8 @@ metacity_SOURCES= \
util.h \
window.c \
window.h \
+ workspace.c \
+ workspace.h \
$(copied_sources)
bin_PROGRAMS=metacity
diff --git a/src/display.c b/src/display.c
index 19e88e4..87a3bfb 100644
--- a/src/display.c
+++ b/src/display.c
@@ -26,6 +26,8 @@
#include "window.h"
#include "frame.h"
#include "errors.h"
+#include "keybindings.h"
+#include "workspace.h"
static GSList *all_displays = NULL;
static void meta_spew_event (MetaDisplay *display,
@@ -75,7 +77,8 @@ meta_display_open (const char *name)
"_NET_WM_NAME",
"WM_PROTOCOLS",
"WM_TAKE_FOCUS",
- "WM_DELETE_WINDOW"
+ "WM_DELETE_WINDOW",
+ "WM_STATE"
};
Atom atoms[G_N_ELEMENTS(atom_names)];
@@ -103,8 +106,12 @@ meta_display_open (const char *name)
display->xdisplay = xdisplay;
display->error_traps = NULL;
+ display->workspaces = NULL;
+
/* we have to go ahead and do this so error handlers work */
all_displays = g_slist_prepend (all_displays, display);
+
+ meta_display_init_keys (display);
screens = NULL;
i = 0;
@@ -147,6 +154,7 @@ meta_display_open (const char *name)
display->atom_wm_protocols = atoms[1];
display->atom_wm_take_focus = atoms[2];
display->atom_wm_delete_window = atoms[3];
+ display->atom_wm_state = atoms[4];
/* Now manage all existing windows */
tmp = display->screens;
@@ -287,10 +295,14 @@ meta_display_ungrab (MetaDisplay *display)
{
if (display->server_grab_count == 0)
meta_bug ("Ungrabbed non-grabbed server\n");
-
+
display->server_grab_count -= 1;
if (display->server_grab_count == 0)
{
+ /* FIXME we want to purge all pending "queued" stuff
+ * at this point, such as window hide/show
+ */
+
XUngrabServer (display->xdisplay);
}
XSync (display->xdisplay, False);
@@ -355,6 +367,7 @@ event_queue_callback (MetaEventQueue *queue,
switch (event->type)
{
case KeyPress:
+ meta_display_process_key_press (display, event);
break;
case KeyRelease:
break;
@@ -429,15 +442,6 @@ event_queue_callback (MetaEventQueue *queue,
case ReparentNotify:
break;
case ConfigureNotify:
- if (window && event->xconfigure.override_redirect)
- {
- /* Unmanage it, override_redirect was toggled on?
- * Can this happen?
- */
- meta_verbose ("Window %s toggled on override redirect\n",
- window->desc);
- meta_window_free (window);
- }
break;
case ConfigureRequest:
/* This comment and code is found in both twm and fvwm */
@@ -755,3 +759,45 @@ meta_display_unregister_x_window (MetaDisplay *display,
g_hash_table_remove (display->window_ids, &xwindow);
}
+
+MetaWorkspace*
+meta_display_get_workspace_by_index (MetaDisplay *display,
+ int index)
+{
+ GList *tmp;
+
+ tmp = g_list_nth (display->workspaces, index);
+
+ if (tmp == NULL)
+ return NULL;
+ else
+ return tmp->data;
+}
+
+MetaWorkspace*
+meta_display_get_workspace_by_screen_index (MetaDisplay *display,
+ MetaScreen *screen,
+ int index)
+{
+ GList *tmp;
+ int i;
+
+ i = 0;
+ tmp = display->workspaces;
+ while (tmp != NULL)
+ {
+ MetaWorkspace *w = tmp->data;
+
+ if (w->screen == screen)
+ {
+ if (i == index)
+ return w;
+ else
+ ++i;
+ }
+
+ tmp = tmp->next;
+ }
+
+ return NULL;
+}
diff --git a/src/display.h b/src/display.h
index 8933d16..6f09257 100644
--- a/src/display.h
+++ b/src/display.h
@@ -27,11 +27,12 @@
#include <pango/pangox.h>
#include "eventqueue.h"
-typedef struct _MetaDisplay MetaDisplay;
-typedef struct _MetaFrame MetaFrame;
-typedef struct _MetaScreen MetaScreen;
-typedef struct _MetaWindow MetaWindow;
-typedef struct _MetaUISlave MetaUISlave;
+typedef struct _MetaDisplay MetaDisplay;
+typedef struct _MetaFrame MetaFrame;
+typedef struct _MetaScreen MetaScreen;
+typedef struct _MetaUISlave MetaUISlave;
+typedef struct _MetaWindow MetaWindow;
+typedef struct _MetaWorkspace MetaWorkspace;
struct _MetaDisplay
{
@@ -42,11 +43,14 @@ struct _MetaDisplay
Atom atom_wm_protocols;
Atom atom_wm_take_focus;
Atom atom_wm_delete_window;
-
+ Atom atom_wm_state;
+
/* This is the actual window from focus events,
* not the one we last set
*/
MetaWindow *focus_window;
+
+ GList *workspaces;
/*< private-ish >*/
MetaEventQueue *events;
@@ -82,4 +86,11 @@ void meta_display_unregister_x_window (MetaDisplay *display,
MetaDisplay* meta_display_for_x_display (Display *xdisplay);
GSList* meta_displays_list (void);
+MetaWorkspace* meta_display_get_workspace_by_index (MetaDisplay *display,
+ int index);
+MetaWorkspace* meta_display_get_workspace_by_screen_index (MetaDisplay *display,
+ MetaScreen *screen,
+ int index);
+
+
#endif
diff --git a/src/frame.c b/src/frame.c
index 92da35f..32e607d 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -24,6 +24,19 @@
#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;
+};
+
+static void clear_tip (MetaFrame *frame);
+
static void
meta_frame_init_info (MetaFrame *frame,
MetaFrameInfo *info)
@@ -47,6 +60,11 @@ meta_frame_init_info (MetaFrame *frame,
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;
}
static void
@@ -201,11 +219,13 @@ meta_window_ensure_frame (MetaWindow *window)
frame = g_new (MetaFrame, 1);
- /* Fill in values that calc_geometry will use */
frame->window = window;
frame->xwindow = None;
frame->theme_acquired = FALSE;
-
+ frame->grab = NULL;
+ frame->current_control = META_FRAME_CONTROL_NONE;
+ frame->tooltip_timeout = 0;
+
/* This fills in frame->rect as well. */
meta_frame_calc_geometry (frame,
window->rect.width,
@@ -226,7 +246,10 @@ meta_window_ensure_frame (MetaWindow *window)
attrs.background_pixel = frame->bg_pixel;
attrs.event_mask =
StructureNotifyMask | SubstructureNotifyMask | ExposureMask |
- ButtonPressMask | ButtonReleaseMask |
+ /* We need OwnerGrabButtonMask because during a button
+ * press we may need to transfer control to the UI slave.
+ */
+ ButtonPressMask | ButtonReleaseMask | OwnerGrabButtonMask |
PointerMotionMask | PointerMotionHintMask |
EnterWindowMask | LeaveWindowMask;
@@ -245,8 +268,6 @@ meta_window_ensure_frame (MetaWindow *window)
meta_verbose ("Frame is 0x%lx\n", frame->xwindow);
- frame->action = META_FRAME_ACTION_NONE;
-
meta_display_register_x_window (window->display, &frame->xwindow, window);
/* Reparent the client window; it may be destroyed,
@@ -277,10 +298,7 @@ meta_window_ensure_frame (MetaWindow *window)
window->frame = frame;
/* Put our state back where it should be */
- if (window->iconic)
- meta_window_hide (window);
- else
- meta_window_show (window);
+ meta_window_queue_calc_showing (window);
/* Ungrab server */
meta_display_ungrab (window->display);
@@ -297,6 +315,9 @@ meta_window_destroy_frame (MetaWindow *window)
frame = window->frame;
+ if (frame->tooltip_timeout)
+ clear_tip (frame);
+
if (frame->theme_data)
{
meta_frame_init_info (frame, &info);
@@ -330,23 +351,7 @@ meta_window_destroy_frame (MetaWindow *window)
g_free (frame);
/* Put our state back where it should be */
- if (window->iconic)
- meta_window_hide (window);
- else
- meta_window_show (window);
-}
-
-void
-meta_frame_move (MetaFrame *frame,
- int root_x,
- int root_y)
-{
- frame->rect.x = root_x;
- frame->rect.y = root_y;
-
- XMoveWindow (frame->window->display->xdisplay,
- frame->xwindow,
- root_x, root_y);
+ meta_window_queue_calc_showing (window);
}
/* Just a chunk of process_configure_event in window.c,
@@ -414,6 +419,8 @@ meta_frame_recalc_now (MetaFrame *frame)
frame->window->desc, frame->rect.x, frame->rect.y,
frame->rect.width, frame->rect.height,
frame->child_x, frame->child_y);
+
+ meta_frame_queue_draw (frame);
}
void
@@ -513,48 +520,223 @@ frame_query_root_pointer (MetaFrame *frame,
*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;
- meta_frame_init_info (frame, &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)
+update_move (MetaFrame *frame,
+ int x,
+ int y)
{
- int x, y;
int dx, dy;
- frame_query_root_pointer (frame, &x, &y);
+ dx = x - frame->grab->start_root_x;
+ dy = y - frame->grab->start_root_y;
+
+ 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->start_root_x;
- dy = y - frame->start_root_y;
+ dx = x - frame->grab->start_root_x;
+ dy = y - frame->grab->start_root_y;
- meta_frame_move (frame,
- frame->start_window_x + dx,
- frame->start_window_y + dy);
+ meta_window_resize (frame->window,
+ frame->grab->start_window_x + dx,
+ frame->grab->start_window_y + dy);
}
static void
-update_resize_se (MetaFrame *frame)
+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;
- int dx, dy;
+
+ meta_verbose ("Ungrabbing action %d\n", frame->grab->action);
- frame_query_root_pointer (frame, &x, &y);
+ XUngrabPointer (frame->window->display->xdisplay,
+ time);
- dx = x - frame->start_root_x;
- dy = y - frame->start_root_y;
+ g_free (frame->grab);
+ frame->grab = NULL;
- meta_window_resize (frame->window,
- frame->start_window_x + dx,
- frame->start_window_y + dy);
+ frame_query_root_pointer (frame, &x, &y);
+ update_current_control (frame, x, y);
+
+ /* undisplay ACTIVE state */
+ meta_frame_queue_draw (frame);
+
+ queue_tip (frame);
}
gboolean
@@ -568,12 +750,18 @@ meta_frame_event (MetaFrame *frame,
case KeyRelease:
break;
case ButtonPress:
- if (frame->action == META_FRAME_ACTION_NONE)
+ /* 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_get_control (frame,
- event->xbutton.x,
- event->xbutton.y);
+ control = frame->current_control;
if (((control == META_FRAME_CONTROL_TITLE ||
control == META_FRAME_CONTROL_NONE) &&
@@ -582,12 +770,16 @@ meta_frame_event (MetaFrame *frame,
{
meta_verbose ("Begin move on %s\n",
frame->window->desc);
- frame->action = META_FRAME_ACTION_MOVING;
- frame->start_root_x = event->xbutton.x_root;
- frame->start_root_y = event->xbutton.y_root;
- frame->start_window_x = frame->rect.x;
- frame->start_window_y = frame->rect.y;
- frame->start_button = event->xbutton.button;
+ 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)
@@ -595,63 +787,92 @@ meta_frame_event (MetaFrame *frame,
/* FIXME delete event */
meta_verbose ("Close control clicked on %s\n",
frame->window->desc);
- meta_window_delete (frame->window, event->xbutton.time);
+ grab_action (frame, META_FRAME_ACTION_DELETING,
+ 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);
- frame->action = META_FRAME_ACTION_RESIZING_SE;
- frame->start_root_x = event->xbutton.x_root;
- frame->start_root_y = event->xbutton.y_root;
- frame->start_window_x = frame->window->rect.width;
- frame->start_window_y = frame->window->rect.height;
- frame->start_button = event->xbutton.button;
+ 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;
}
}
break;
case ButtonRelease:
- if (event->xbutton.button == frame->start_button)
+ 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->action)
+ switch (frame->grab->action)
{
case META_FRAME_ACTION_MOVING:
- update_move (frame);
+ 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);
+ 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;
-
default:
+ meta_warning ("Unhandled action in button release\n");
break;
}
-
- frame->action = META_FRAME_ACTION_NONE;
}
break;
case MotionNotify:
- switch (frame->action)
- {
- case META_FRAME_ACTION_MOVING:
- update_move (frame);
- break;
-
- case META_FRAME_ACTION_RESIZING_SE:
- update_resize_se (frame);
- break;
-
- case META_FRAME_ACTION_NONE:
-#if 0
- meta_ui_slave_show_tip (frame->window->screen->uislave,
- frame->rect.x,
- frame->rect.y,
- "Hi this is a tooltip");
-#endif
- break;
- default:
- break;
+ {
+ 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:
@@ -663,6 +884,7 @@ meta_frame_event (MetaFrame *frame,
event->xcrossing.time);
break;
case LeaveNotify:
+ update_current_control (frame, -1, -1);
break;
case FocusIn:
break;
@@ -698,10 +920,12 @@ meta_frame_event (MetaFrame *frame,
}
break;
case UnmapNotify:
- frame->action = META_FRAME_ACTION_NONE;
+ if (frame->grab)
+ ungrab_action (frame, CurrentTime);
break;
case MapNotify:
- frame->action = META_FRAME_ACTION_NONE;
+ if (frame->grab)
+ ungrab_action (frame, CurrentTime);
break;
case MapRequest:
break;
diff --git a/src/frame.h b/src/frame.h
index 0757d7a..0b5f2a0 100644
--- a/src/frame.h
+++ b/src/frame.h
@@ -28,9 +28,12 @@ typedef enum
{
META_FRAME_ACTION_NONE,
META_FRAME_ACTION_MOVING,
+ META_FRAME_ACTION_DELETING,
META_FRAME_ACTION_RESIZING_SE
} MetaFrameAction;
+typedef struct _MetaFrameActionGrab MetaFrameActionGrab;
+
struct _MetaFrame
{
/* window we frame */
@@ -48,23 +51,18 @@ struct _MetaFrame
gpointer theme_data;
gulong bg_pixel;
-
- 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;
+ MetaFrameActionGrab *grab;
+
+ MetaFrameControl current_control;
+
+ guint tooltip_timeout;
+
guint theme_acquired : 1;
};
void meta_window_ensure_frame (MetaWindow *window);
void meta_window_destroy_frame (MetaWindow *window);
-void meta_frame_move (MetaFrame *frame,
- int root_x,
- 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);
diff --git a/src/keybindings.c b/src/keybindings.c
new file mode 100644
index 0000000..56ab364
--- /dev/null
+++ b/src/keybindings.c
@@ -0,0 +1,172 @@
+/* Metacity Keybindings */
+
+/*
+ * 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 "keybindings.h"
+#include "workspace.h"
+#include "errors.h"
+
+#include <X11/keysym.h>
+
+/* Plainly we'll want some more configurable keybinding system
+ * eventually.
+ */
+
+typedef void (* MetaKeyHandler) (MetaDisplay *display,
+ XEvent *event,
+ gpointer data);
+
+static void handle_activate_workspace (MetaDisplay *display,
+ XEvent *event,
+ gpointer data);
+
+typedef struct _MetaKeyBinding MetaKeyBinding;
+
+struct _MetaKeyBinding
+{
+ KeySym keysym;
+ gulong mask;
+ MetaKeyHandler handler;
+ gpointer data;
+ int keycode;
+};
+
+#define INTERESTING_MODIFIERS (ShiftMask | ControlMask | Mod1Mask)
+
+static MetaKeyBinding bindings[] = {
+ { XK_F1, Mod1Mask, handle_activate_workspace, GINT_TO_POINTER (0), 0 },
+ { XK_F2, Mod1Mask, handle_activate_workspace, GINT_TO_POINTER (1), 0 }
+};
+
+void
+meta_display_init_keys (MetaDisplay *display)
+{
+ int i;
+
+ i = 0;
+ while (i < G_N_ELEMENTS (bindings))
+ {
+ bindings[i].keycode = XKeysymToKeycode (display->xdisplay,
+ bindings[i].keysym);
+
+ ++i;
+ }
+}
+
+void
+meta_screen_grab_keys (MetaScreen *screen)
+{
+ int i;
+
+ i = 0;
+ while (i < G_N_ELEMENTS (bindings))
+ {
+ if (bindings[i].keycode != 0)
+ {
+ int result;
+
+ meta_error_trap_push (screen->display);
+ XGrabKey (screen->display->xdisplay, bindings[i].keycode,
+ bindings[i].mask, screen->xroot, True,
+ GrabModeAsync, GrabModeAsync);
+ result = meta_error_trap_pop (screen->display);
+ if (result != Success)
+ {
+ const char *name;
+
+ name = XKeysymToString (bindings[i].keysym);
+ if (name == NULL)
+ name = "(unknown)";
+
+ if (result == BadAccess)
+ meta_warning (_("Some other program is already using the key %s as a binding\n"), name);
+ else
+ meta_bug ("Unexpected error setting up keybindings\n");
+ }
+ }
+
+ ++i;
+ }
+}
+
+void
+meta_screen_ungrab_keys (MetaScreen *screen)
+{
+ int i;
+
+ i = 0;
+ while (i < G_N_ELEMENTS (bindings))
+ {
+ if (bindings[i].keycode != 0)
+ {
+ XUngrabKey (screen->display->xdisplay, bindings[i].keycode,
+ bindings[i].mask, screen->xroot);
+ }
+
+ ++i;
+ }
+}
+
+void
+meta_display_process_key_press (MetaDisplay *display,
+ XEvent *event)
+{
+ KeySym keysym;
+ int i;
+
+ keysym = XKeycodeToKeysym (display->xdisplay, event->xkey.keycode, 0);
+
+ i = 0;
+ while (i < G_N_ELEMENTS (bindings))
+ {
+ if (bindings[i].keysym == keysym &&
+ ((event->xkey.state & INTERESTING_MODIFIERS) ==
+ bindings[i].mask))
+ {
+ (* bindings[i].handler) (display, event, bindings[i].data);
+ break;
+ }
+
+ ++i;
+ }
+}
+
+static void
+handle_activate_workspace (MetaDisplay *display,
+ XEvent *event,
+ gpointer data)
+{
+ int which;
+ MetaWorkspace *workspace;
+
+ which = GPOINTER_TO_INT (data);
+
+ workspace = meta_display_get_workspace_by_index (display, which);
+
+ if (workspace)
+ {
+ meta_workspace_activate (workspace);
+ }
+ else
+ {
+ /* We could offer to create it I suppose */
+ }
+}
+
diff --git a/src/keybindings.h b/src/keybindings.h
new file mode 100644
index 0000000..9f252f0
--- /dev/null
+++ b/src/keybindings.h
@@ -0,0 +1,37 @@
+/* Metacity Keybindings */
+
+/*
+ * 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_KEYBINDINGS_H
+#define META_KEYBINDINGS_H
+
+#include "display.h"
+
+void meta_display_init_keys (MetaDisplay *display);
+void meta_screen_grab_keys (MetaScreen *screen);
+void meta_screen_ungrab_keys (MetaScreen *screen);
+void meta_display_process_key_press (MetaDisplay *display,
+ XEvent *event);
+
+#endif
+
+
+
+
diff --git a/src/screen.c b/src/screen.c
index f47e650..b79b44b 100644
--- a/src/screen.c
+++ b/src/screen.c
@@ -26,6 +26,8 @@
#include "colors.h"
#include "uislave.h"
#include "frame.h"
+#include "workspace.h"
+#include "keybindings.h"
#include <X11/cursorfont.h>
#include <locale.h>
@@ -100,9 +102,20 @@ meta_screen_new (MetaDisplay *display,
screen->engine = &meta_default_engine;
+ screen->showing_tooltip = FALSE;
+
+ /* Screens must have at least one workspace at all times,
+ * so create that required workspace.
+ */
+ screen->active_workspace = meta_workspace_new (screen);
+ /* FIXME, for debugging create another one. */
+ meta_workspace_new (screen);
+
meta_screen_init_visual_info (screen);
meta_screen_init_ui_colors (screen);
+ meta_screen_grab_keys (screen);
+
screen->scratch_gc = XCreateGC (screen->display->xdisplay,
screen->xroot,
0,
@@ -121,6 +134,8 @@ meta_screen_new (MetaDisplay *display,
void
meta_screen_free (MetaScreen *screen)
{
+ meta_screen_ungrab_keys (screen);
+
meta_ui_slave_free (screen->uislave);
XFreeGC (screen->display->xdisplay,
@@ -419,3 +434,25 @@ meta_screen_queue_frame_redraws (MetaScreen *screen)
{
meta_screen_foreach_window (screen, queue_draw, NULL);
}
+
+
+void
+meta_screen_show_tip (MetaScreen *screen,
+ int root_x,
+ int root_y,
+ const char *markup)
+{
+ /* even if screen->showing_tip, may change position/text */
+ meta_ui_slave_show_tip (screen->uislave, root_x, root_y, markup);
+ screen->showing_tooltip = TRUE;
+}
+
+void
+meta_screen_hide_tip (MetaScreen *screen)
+{
+ if (screen->showing_tooltip)
+ {
+ meta_ui_slave_hide_tip (screen->uislave);
+ screen->showing_tooltip = FALSE;
+ }
+}
diff --git a/src/screen.h b/src/screen.h
index 42cca88..93de5bc 100644
--- a/src/screen.h
+++ b/src/screen.h
@@ -39,6 +39,8 @@ struct _MetaScreen
MetaThemeEngine *engine;
MetaUISlave *uislave;
+ MetaWorkspace *active_workspace;
+
XVisualInfo visual_info;
MetaUIColors colors;
@@ -46,6 +48,8 @@ struct _MetaScreen
* left with a clip.
*/
GC scratch_gc;
+
+ guint showing_tooltip : 1;
/*< private >*/
@@ -68,6 +72,12 @@ void meta_screen_foreach_window (MetaScreen *scree
gpointer data);
void meta_screen_queue_frame_redraws (MetaScreen *screen);
+void meta_screen_show_tip (MetaScreen *screen,
+ int root_x,
+ int root_y,
+ const char *markup);
+
+void meta_screen_hide_tip (MetaScreen *screen);
#endif
diff --git a/src/theme.c b/src/theme.c
index 2db9c51..700a2e6 100644
--- a/src/theme.c
+++ b/src/theme.c
@@ -58,6 +58,8 @@ struct _DefaultScreenData
GC black_gc;
GC selected_gc;
GC selected_text_gc;
+ GC active_gc;
+ GC prelight_gc;
};
/* FIXME store this on the screen */
@@ -114,6 +116,21 @@ default_acquire_frame (MetaFrameInfo *info)
RootWindowOfScreen (info->screen),
GCForeground,
&vals);
+
+ vals.foreground = meta_get_x_pixel (info->screen,
+ &info->colors->bg[META_STATE_ACTIVE]);
+ screen_data->active_gc = XCreateGC (info->display,
+ RootWindowOfScreen (info->screen),
+ GCForeground,
+ &vals);
+
+ vals.foreground = meta_get_x_pixel (info->screen,
+ &info->colors->bg[META_STATE_PRELIGHT]);
+ screen_data->prelight_gc = XCreateGC (info->display,
+ RootWindowOfScreen (info->screen),
+ GCForeground,
+ &vals);
+
color.red = color.green = color.blue = 0;
vals.foreground = meta_get_x_pixel (info->screen,
@@ -422,6 +439,97 @@ set_clip (Display *display, GC gc, MetaRectangle *rect)
}
}
+static MetaRectangle*
+control_rect (MetaFrameControl control,
+ DefaultFrameGeometry *fgeom)
+{
+ MetaRectangle *rect;
+
+ rect = NULL;
+ switch (control)
+ {
+ case META_FRAME_CONTROL_TITLE:
+ rect = &fgeom->title_rect;
+ break;
+ case META_FRAME_CONTROL_DELETE:
+ rect = &fgeom->close_rect;
+ break;
+ case META_FRAME_CONTROL_MENU:
+ rect = &fgeom->menu_rect;
+ break;
+ case META_FRAME_CONTROL_ICONIFY:
+ rect = &fgeom->min_rect;
+ break;
+ case META_FRAME_CONTROL_MAXIMIZE:
+ rect = &fgeom->max_rect;
+ 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;
+ }
+
+ return rect;
+}
+
+static void
+draw_current_control_bg (MetaFrameInfo *info,
+ DefaultFrameGeometry *fgeom)
+{
+ int xoff, yoff;
+ MetaRectangle *rect;
+
+ xoff = info->xoffset;
+ yoff = info->yoffset;
+
+ rect = control_rect (info->current_control, fgeom);
+
+ if (rect == NULL)
+ return;
+
+ if (info->current_control == META_FRAME_CONTROL_TITLE)
+ return;
+
+ switch (info->current_control_state)
+ {
+ /* FIXME turn this off after testing */
+ case META_STATE_PRELIGHT:
+ XFillRectangle (info->display,
+ info->drawable,
+ screen_data->prelight_gc,
+ xoff + rect->x,
+ yoff + rect->y,
+ rect->width, rect->height);
+ break;
+
+ case META_STATE_ACTIVE:
+ XFillRectangle (info->display,
+ info->drawable,
+ screen_data->active_gc,
+ xoff + rect->x,
+ yoff + rect->y,
+ rect->width, rect->height);
+ break;
+
+ default:
+ break;
+ }
+}
+
static void
default_expose_frame (MetaFrameInfo *info,
int x, int y,
@@ -483,6 +591,8 @@ default_expose_frame (MetaFrameInfo *info,
info->width - fgeom.right_width - fgeom.left_width + 1,
info->height - fgeom.bottom_height - fgeom.top_height + 1);
}
+
+ draw_current_control_bg (info, &fgeom);
if (fgeom.title_rect.width > 0 && fgeom.title_rect.height > 0)
{
@@ -527,7 +637,7 @@ default_expose_frame (MetaFrameInfo *info,
}
if (fgeom.close_rect.width > 0 && fgeom.close_rect.height > 0)
- {
+ {
XDrawLine (info->display,
info->drawable,
screen_data->fg_gc,
@@ -644,6 +754,15 @@ default_get_control (MetaFrameInfo *info,
if (POINT_IN_RECT (x, y, fgeom.close_rect))
return META_FRAME_CONTROL_DELETE;
+
+ if (POINT_IN_RECT (x, y, fgeom.min_rect))
+ return META_FRAME_CONTROL_ICONIFY;
+
+ if (POINT_IN_RECT (x, y, fgeom.max_rect))
+ return META_FRAME_CONTROL_MAXIMIZE;
+
+ if (POINT_IN_RECT (x, y, fgeom.menu_rect))
+ return META_FRAME_CONTROL_MENU;
if (POINT_IN_RECT (x, y, fgeom.title_rect))
return META_FRAME_CONTROL_TITLE;
@@ -655,6 +774,36 @@ default_get_control (MetaFrameInfo *info,
return META_FRAME_CONTROL_NONE;
}
+static void
+default_get_control_rect (MetaFrameInfo *info,
+ MetaFrameControl control,
+ int *x, int *y,
+ int *width, int *height,
+ gpointer frame_data)
+{
+ MetaRectangle *rect;
+ DefaultFrameData *d;
+ DefaultFrameGeometry fgeom;
+
+ d = frame_data;
+
+ calc_geometry (info, d, &fgeom);
+
+ rect = control_rect (control, &fgeom);
+
+ if (rect)
+ {
+ *x = rect->x;
+ *y = rect->y;
+ *width = rect->width;
+ *height = rect->height;
+ }
+ else
+ {
+ *x = *y = *width = *height = 0;
+ }
+}
+
/* FIXME add this to engine vtable */
static void
default_release_screen (Screen *screen)
@@ -668,6 +817,8 @@ default_release_screen (Screen *screen)
XFreeGC (DisplayOfScreen (screen), screen_data->black_gc);
XFreeGC (DisplayOfScreen (screen), screen_data->light_gc);
XFreeGC (DisplayOfScreen (screen), screen_data->dark_gc);
+ XFreeGC (DisplayOfScreen (screen), screen_data->active_gc);
+ XFreeGC (DisplayOfScreen (screen), screen_data->prelight_gc);
}
}
@@ -677,5 +828,6 @@ MetaThemeEngine meta_default_engine = {
default_release_frame,
default_fill_frame_geometry,
default_expose_frame,
- default_get_control
+ default_get_control,
+ default_get_control_rect
};
diff --git a/src/theme.h b/src/theme.h
index 5fdea6d..5a7a9b9 100644
--- a/src/theme.h
+++ b/src/theme.h
@@ -76,6 +76,9 @@ struct _MetaFrameInfo
const char *title;
const MetaUIColors *colors;
+
+ MetaFrameControl current_control;
+ MetaUIState current_control_state;
/* Equal to child size before fill_frame_geometry
* has been called
@@ -121,6 +124,12 @@ struct _MetaThemeEngine
MetaFrameControl (* get_control) (MetaFrameInfo *info,
int x, int y,
gpointer frame_data);
+
+ void (* get_control_rect) (MetaFrameInfo *info,
+ MetaFrameControl control,
+ int *x, int *y,
+ int *width, int *height,
+ gpointer frame_data);
};
extern MetaThemeEngine meta_default_engine;
diff --git a/src/uislave.c b/src/uislave.c
index 994cb59..680bb10 100644
--- a/src/uislave.c
+++ b/src/uislave.c
@@ -305,3 +305,15 @@ meta_ui_slave_show_tip (MetaUISlave *uislave,
send_message (uislave, (MetaMessage*)&showtip);
}
+
+void
+meta_ui_slave_hide_tip (MetaUISlave *uislave)
+{
+ MetaMessageHideTip hidetip;
+
+ memset (&hidetip, 0, META_MESSAGE_LENGTH (MetaMessageHideTip));
+ hidetip.header.message_code = MetaMessageHideTipCode;
+ hidetip.header.length = META_MESSAGE_LENGTH (MetaMessageHideTip);
+
+ send_message (uislave, (MetaMessage*)&hidetip);
+}
diff --git a/src/uislave.h b/src/uislave.h
index 09c59dd..673901b 100644
--- a/src/uislave.h
+++ b/src/uislave.h
@@ -62,5 +62,6 @@ void meta_ui_slave_show_tip (MetaUISlave *uislave,
int root_x,
int root_y,
const char *markup_text);
+void meta_ui_slave_hide_tip (MetaUISlave *uislave);
#endif
diff --git a/src/uislave/main.c b/src/uislave/main.c
index fc4f9ae..284fbd2 100644
--- a/src/uislave/main.c
+++ b/src/uislave/main.c
@@ -63,6 +63,10 @@ message_callback (MetaMessageQueue *mq,
message->show_tip.root_y,
message->show_tip.markup);
break;
+
+ case MetaMessageHideTipCode:
+ meta_fixed_tip_hide ();
+ break;
default:
meta_ui_warning ("Unhandled message code %d\n",
diff --git a/src/window.c b/src/window.c
index 32037f8..4b6a75f 100644
--- a/src/window.c
+++ b/src/window.c
@@ -23,22 +23,33 @@
#include "util.h"
#include "frame.h"
#include "errors.h"
+#include "workspace.h"
+
#include <X11/Xatom.h>
-static void constrain_size (MetaWindow *window,
- int width,
- int height,
- int *new_width,
- int *new_height);
-static int update_size_hints (MetaWindow *window);
-static int update_title (MetaWindow *window);
-static int update_protocols (MetaWindow *window);
-static int update_wm_hints (MetaWindow *window);
-static gboolean process_configure_request (MetaWindow *window,
- int x, int y, int width, int height,
- int border_width);
-static gboolean process_property_notify (MetaWindow *window,
- XPropertyEvent *event);
+static void constrain_size (MetaWindow *window,
+ int width,
+ int height,
+ int *new_width,
+ int *new_height);
+static int update_size_hints (MetaWindow *window);
+static int update_title (MetaWindow *window);
+static int update_protocols (MetaWindow *window);
+static int update_wm_hints (MetaWindow *window);
+static int set_wm_state (MetaWindow *window,
+ int state);
+static void send_configure_notify (MetaWindow *window);
+static gboolean process_configure_request (MetaWindow *window,
+ int x,
+ int y,
+ int width,
+ int height,
+ int border_width);
+static gboolean process_property_notify (MetaWindow *window,
+ XPropertyEvent *event);
+static void meta_window_show (MetaWindow *window);
+static void meta_window_hide (MetaWindow *window);
+
MetaWindow*
meta_window_new (MetaDisplay *display, Window xwindow)
@@ -88,6 +99,7 @@ meta_window_new (MetaDisplay *display, Window xwindow)
* type
*/
window->display = display;
+ window->workspaces = NULL;
window->screen = NULL;
tmp = display->screens;
@@ -141,21 +153,26 @@ meta_window_new (MetaDisplay *display, Window xwindow)
if (window->initially_iconic)
{
- /* WM_HINTS said iconic */
- window->iconic = TRUE;
+ /* WM_HINTS said minimized */
+ window->minimized = TRUE;
+ meta_verbose ("Window %s asked to start out minimized\n", window->desc);
}
- meta_window_resize (window, window->size_hints.width, window->size_hints.height);
+ meta_window_resize (window,
+ window->size_hints.width,
+ window->size_hints.height);
+
+ /* FIXME we have a tendency to set this then immediately
+ * change it again.
+ */
+ set_wm_state (window, window->iconic ? IconicState : NormalState);
meta_window_ensure_frame (window);
- /* Put our state where it should be (ensure_frame also did this
- * for decorated windows, but should be harmless to do twice)
- */
- if (window->iconic)
- meta_window_hide (window);
- else
- meta_window_show (window);
+ meta_workspace_add_window (window->screen->active_workspace, window);
+
+ /* Put our state back where it should be */
+ meta_window_queue_calc_showing (window);
return window;
}
@@ -163,7 +180,26 @@ meta_window_new (MetaDisplay *display, Window xwindow)
void
meta_window_free (MetaWindow *window)
{
+ GList *tmp;
+
meta_verbose ("Unmanaging 0x%lx\n", window->xwindow);
+
+ tmp = window->workspaces;
+ while (tmp != NULL)
+ {
+ GList *next;
+
+ next = tmp->next;
+
+ /* pops front of list */
+ meta_workspace_remove_window (tmp->data, window);
+
+ tmp = next;
+ }
+
+ g_assert (window->workspaces == NULL);
+
+ set_wm_state (window, WithdrawnState);
meta_display_unregister_x_window (window->display, window->xwindow);
@@ -183,9 +219,64 @@ meta_window_free (MetaWindow *window)
g_free (window);
}
+static int
+set_wm_state (MetaWindow *window,
+ int state)
+{
+ unsigned long data[1];
+
+ /* twm sets the icon window as data[1], I couldn't find that in
+ * ICCCM.
+ */
+ data[0] = state;
+
+ meta_error_trap_push (window->display);
+ XChangeProperty (window->display->xdisplay, window->xwindow,
+ window->display->atom_wm_state,
+ window->display->atom_wm_state,
+ 32, PropModeReplace, (guchar*) data, 1);
+ return meta_error_trap_pop (window->display);
+}
+
+void
+meta_window_calc_showing (MetaWindow *window)
+{
+ gboolean on_workspace;
+
+ on_workspace = g_list_find (window->workspaces,
+ window->screen->active_workspace) != NULL;
+
+ if (!on_workspace)
+ meta_verbose ("Window %s is not on workspace %d\n",
+ window->desc,
+ meta_workspace_index (window->screen->active_workspace));
+ else
+ meta_verbose ("Window %s is on the active workspace %d\n",
+ window->desc,
+ meta_workspace_index (window->screen->active_workspace));
+
+ if (window->minimized || !on_workspace)
+ {
+ meta_window_hide (window);
+ }
+ else
+ {
+ meta_window_show (window);
+ }
+}
+
+void
+meta_window_queue_calc_showing (MetaWindow *window)
+{
+ /* FIXME */
+ meta_window_calc_showing (window);
+}
+
void
meta_window_show (MetaWindow *window)
{
+ meta_verbose ("Showing window %s\n", window->desc);
+
if (window->frame)
XMapWindow (window->display->xdisplay, window->frame->xwindow);
XMapWindow (window->display->xdisplay, window->xwindow);
@@ -193,25 +284,33 @@ meta_window_show (MetaWindow *window)
/* These flags aren't always in sync, iconic
* is set only here in show/hide, mapped
* can be set in a couple other places where
- * we map/unmap
+ * we map/unmap. So that's why both flags exist.
*/
window->mapped = TRUE;
- window->iconic = FALSE;
- /* FIXME update WM_STATE */
+ if (window->iconic)
+ {
+ window->iconic = FALSE;
+ set_wm_state (window, NormalState);
+ }
}
void
meta_window_hide (MetaWindow *window)
{
+ meta_verbose ("Hiding window %s\n", window->desc);
+
if (window->frame)
XUnmapWindow (window->display->xdisplay, window->frame->xwindow);
XUnmapWindow (window->display->xdisplay, window->xwindow);
window->mapped = FALSE;
- window->iconic = TRUE;
- /* FIXME update WM_STATE */
+ if (!window->iconic)
+ {
+ window->iconic = TRUE;
+ set_wm_state (window, IconicState);
+ }
}
void
@@ -260,6 +359,48 @@ meta_window_resize (MetaWindow *window,
}
void
+meta_window_move (MetaWindow *window,
+ int root_x_nw,
+ int root_y_nw)
+{
+ if (window->frame)
+ {
+ int new_x, new_y;
+
+ new_x = root_x_nw - window->frame->child_x;
+ new_y = root_y_nw - window->frame->child_y;
+
+ if (new_x != window->frame->rect.x ||
+ new_y != window->frame->rect.y)
+ {
+ window->frame->rect.x = new_x;
+ window->frame->rect.y = new_y;
+
+ XMoveWindow (window->display->xdisplay,
+ window->frame->xwindow,
+ window->frame->rect.x,
+ window->frame->rect.y);
+ }
+ }
+ else
+ {
+ if (root_x_nw != window->rect.x ||
+ root_y_nw != window->rect.y)
+ {
+ window->rect.x = root_x_nw;
+ window->rect.y = root_y_nw;
+
+ XMoveWindow (window->display->xdisplay,
+ window->xwindow,
+ window->rect.x,
+ window->rect.y);
+ }
+ }
+
+ send_configure_notify (window);
+}
+
+void
meta_window_delete (MetaWindow *window,
Time timestamp)
{
@@ -309,6 +450,26 @@ meta_window_focus (MetaWindow *window,
}
void
+meta_window_raise (MetaWindow *window)
+{
+ meta_verbose ("Raising window %s\n", window->desc);
+
+ if (window->frame == NULL)
+ {
+ meta_error_trap_push (window->display);
+
+ XRaiseWindow (window->display->xdisplay, window->xwindow);
+
+ meta_error_trap_pop (window->display);
+ }
+ else
+ {
+ XRaiseWindow (window->display->xdisplay,
+ window->frame->xwindow);
+ }
+}
+
+void
meta_window_send_icccm_message (MetaWindow *window,
Atom atom,
Time timestamp)
diff --git a/src/window.h b/src/window.h
index 453318d..70c2a11 100644
--- a/src/window.h
+++ b/src/window.h
@@ -30,6 +30,7 @@ struct _MetaWindow
{
MetaDisplay *display;
MetaScreen *screen;
+ GList *workspaces;
Window xwindow;
/* may be NULL! not all windows get decorated */
MetaFrame *frame;
@@ -51,7 +52,7 @@ struct _MetaWindow
*/
guint iconic : 1;
/* initially_iconic is the WM_HINTS setting when we first manage
- * the window.
+ * the window. It's taken to mean initially minimized.
*/
guint initially_iconic : 1;
@@ -75,20 +76,27 @@ struct _MetaWindow
XSizeHints size_hints;
};
-MetaWindow* meta_window_new (MetaDisplay *display,
- Window xwindow);
-void meta_window_free (MetaWindow *window);
-void meta_window_show (MetaWindow *window);
-void meta_window_hide (MetaWindow *window);
-void meta_window_minimize (MetaWindow *window);
-void meta_window_unminimize (MetaWindow *window);
-void meta_window_resize (MetaWindow *window,
- int w,
- int h);
-void meta_window_delete (MetaWindow *window,
- Time timestamp);
-void meta_window_focus (MetaWindow *window,
- Time timestamp);
+MetaWindow* meta_window_new (MetaDisplay *display,
+ Window xwindow);
+void meta_window_free (MetaWindow *window);
+void meta_window_calc_showing (MetaWindow *window);
+void meta_window_queue_calc_showing (MetaWindow *window);
+void meta_window_minimize (MetaWindow *window);
+void meta_window_unminimize (MetaWindow *window);
+void meta_window_resize (MetaWindow *window,
+ int w,
+ int h);
+
+/* args to move are window pos, not frame pos */
+void meta_window_move (MetaWindow *window,
+ int root_x_nw,
+ int root_y_nw);
+void meta_window_delete (MetaWindow *window,
+ Time timestamp);
+void meta_window_focus (MetaWindow *window,
+ Time timestamp);
+void meta_window_raise (MetaWindow *window);
+
/* Sends a client message */
void meta_window_send_icccm_message (MetaWindow *window,
diff --git a/src/workspace.c b/src/workspace.c
new file mode 100644
index 0000000..d0e2339
--- /dev/null
+++ b/src/workspace.c
@@ -0,0 +1,141 @@
+/* Metacity Workspaces */
+
+/*
+ * 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 "workspace.h"
+
+void meta_workspace_queue_calc_showing (MetaWorkspace *workspace);
+
+MetaWorkspace*
+meta_workspace_new (MetaScreen *screen)
+{
+ MetaWorkspace *workspace;
+
+ workspace = g_new (MetaWorkspace, 1);
+
+ workspace->screen = screen;
+ workspace->screen->display->workspaces =
+ g_list_append (workspace->screen->display->workspaces, workspace);
+ workspace->windows = NULL;
+
+ return workspace;
+}
+
+void
+meta_workspace_free (MetaWorkspace *workspace)
+{
+ GList *tmp;
+
+ tmp = workspace->windows;
+ while (tmp != NULL)
+ {
+ GList *next;
+ next = tmp->next;
+ /* pop front of list */
+ meta_workspace_remove_window (workspace, tmp->data);
+
+ tmp = next;
+ }
+
+ g_assert (workspace->windows == NULL);
+
+ workspace->screen->display->workspaces =
+ g_list_remove (workspace->screen->display->workspaces, workspace);
+
+ g_free (workspace);
+}
+
+void
+meta_workspace_add_window (MetaWorkspace *workspace,
+ MetaWindow *window)
+{
+ g_return_if_fail (g_list_find (workspace->windows, window) == NULL);
+
+ workspace->windows = g_list_prepend (workspace->windows, window);
+ window->workspaces = g_list_prepend (window->workspaces, workspace);
+
+ meta_window_queue_calc_showing (window);
+}
+
+void
+meta_workspace_remove_window (MetaWorkspace *workspace,
+ MetaWindow *window)
+{
+ g_return_if_fail (g_list_find (workspace->windows, window) != NULL);
+
+ workspace->windows = g_list_remove (workspace->windows, window);
+ window->workspaces = g_list_remove (window->workspaces, workspace);
+
+ meta_window_queue_calc_showing (window);
+}
+
+void
+meta_workspace_queue_calc_showing (MetaWorkspace *workspace)
+{
+ GList *tmp;
+
+ tmp = workspace->windows;
+ while (tmp != NULL)
+ {
+ meta_window_queue_calc_showing (tmp->data);
+
+ tmp = tmp->next;
+ }
+}
+
+void
+meta_workspace_activate (MetaWorkspace *workspace)
+{
+ MetaWorkspace *old;
+
+ meta_verbose ("Activating workspace %d\n",
+ meta_workspace_index (workspace));
+
+ if (workspace->screen->active_workspace == workspace)
+ return;
+
+ old = workspace->screen->active_workspace;
+
+ workspace->screen->active_workspace = workspace;
+
+ meta_workspace_queue_calc_showing (old);
+ meta_workspace_queue_calc_showing (workspace);
+}
+
+int
+meta_workspace_index (MetaWorkspace *workspace)
+{
+ GList *tmp;
+ int i;
+
+ i = 0;
+ tmp = workspace->screen->display->workspaces;
+ while (tmp != NULL)
+ {
+ if (tmp->data == workspace)
+ return i;
+
+ ++i;
+
+ tmp = tmp->next;
+ }
+
+ meta_bug ("Workspace does not exist to index!\n");
+}
diff --git a/src/workspace.h b/src/workspace.h
new file mode 100644
index 0000000..dcf808d
--- /dev/null
+++ b/src/workspace.h
@@ -0,0 +1,48 @@
+/* Metacity Workspaces */
+
+/*
+ * 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_WORKSPACE_H
+#define META_WORKSPACE_H
+
+#include "window.h"
+
+struct _MetaWorkspace
+{
+ MetaScreen *screen;
+
+ GList *windows;
+};
+
+MetaWorkspace* meta_workspace_new (MetaScreen *screen);
+void meta_workspace_free (MetaWorkspace *workspace);
+void meta_workspace_add_window (MetaWorkspace *workspace,
+ MetaWindow *window);
+void meta_workspace_remove_window (MetaWorkspace *workspace,
+ MetaWindow *window);
+
+void meta_workspace_activate (MetaWorkspace *workspace);
+int meta_workspace_index (MetaWorkspace *workspace);
+
+#endif
+
+
+
+