summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorrhp <rhp>2001-06-10 03:17:15 +0000
committerrhp <rhp>2001-06-10 03:17:15 +0000
commitb5e506ce9d65a5f51bad1df86d21bf3d98e99155 (patch)
tree436273deef61eab43eedddc7668f2a7a34adfee0 /src
parent146361b6f577286ac513feeb41c1675bf487a33b (diff)
downloadmetacity-b5e506ce9d65a5f51bad1df86d21bf3d98e99155.tar.gz
metacity-b5e506ce9d65a5f51bad1df86d21bf3d98e99155.tar.bz2
...
Diffstat (limited to 'src')
-rw-r--r--src/display.c78
-rw-r--r--src/display.h11
-rw-r--r--src/frame.c46
-rw-r--r--src/frame.h5
-rw-r--r--src/menu.c114
-rw-r--r--src/screen.c52
-rw-r--r--src/screen.h2
-rw-r--r--src/theme.c8
-rw-r--r--src/theme.h3
-rw-r--r--src/uislave/menu.c114
-rw-r--r--src/uislave/messages.h4
-rw-r--r--src/window.c451
-rw-r--r--src/window.h27
-rw-r--r--src/workspace.c52
-rw-r--r--src/workspace.h3
15 files changed, 752 insertions, 218 deletions
diff --git a/src/display.c b/src/display.c
index 196224b..2cf29e0 100644
--- a/src/display.c
+++ b/src/display.c
@@ -28,6 +28,8 @@
#include "errors.h"
#include "keybindings.h"
#include "workspace.h"
+#include <X11/Xatom.h>
+#include <string.h>
static GSList *all_displays = NULL;
static void meta_spew_event (MetaDisplay *display,
@@ -61,6 +63,19 @@ unsigned_long_hash (gconstpointer v)
#endif
}
+static int
+set_string_hint (MetaDisplay *display,
+ Window xwindow,
+ Atom atom,
+ const char *val)
+{
+ meta_error_trap_push (display);
+ XChangeProperty (display->xdisplay,
+ xwindow, atom,
+ XA_STRING,
+ 8, PropModeReplace, (guchar*) val, strlen (val) + 1);
+ return meta_error_trap_pop (display);
+}
gboolean
meta_display_open (const char *name)
@@ -90,7 +105,18 @@ meta_display_open (const char *name)
"WM_CHANGE_STATE",
"SM_CLIENT_ID",
"WM_CLIENT_LEADER",
- "WM_WINDOW_ROLE"
+ "WM_WINDOW_ROLE",
+ "_NET_CURRENT_DESKTOP",
+ "_NET_SUPPORTING_WM_CHECK",
+ "_NET_WM_SUPPORTED",
+ "_NET_WM_WINDOW_TYPE",
+ "_NET_WM_WINDOW_TYPE_DESKTOP",
+ "_NET_WM_WINDOW_TYPE_DOCK",
+ "_NET_WM_WINDOW_TYPE_TOOLBAR",
+ "_NET_WM_WINDOW_TYPE_MENU",
+ "_NET_WM_WINDOW_TYPE_DIALOG",
+ "_NET_WM_WINDOW_TYPE_NORMAL",
+ "_NET_WM_STATE_MODAL"
};
Atom atoms[G_N_ELEMENTS(atom_names)];
@@ -144,6 +170,17 @@ meta_display_open (const char *name)
display->atom_sm_client_id = atoms[14];
display->atom_wm_client_leader = atoms[15];
display->atom_wm_window_role = atoms[16];
+ display->atom_net_current_desktop = atoms[17];
+ display->atom_net_supporting_wm_check = atoms[18];
+ display->atom_net_wm_supported = atoms[19];
+ display->atom_net_wm_window_type = atoms[20];
+ display->atom_net_wm_window_type_desktop = atoms[21];
+ display->atom_net_wm_window_type_dock = atoms[22];
+ display->atom_net_wm_window_type_toolbar = atoms[23];
+ display->atom_net_wm_window_type_menu = atoms[24];
+ display->atom_net_wm_window_type_dialog = atoms[25];
+ display->atom_net_wm_window_type_normal = atoms[26];
+ display->atom_net_wm_state_modal = atoms[27];
screens = NULL;
i = 0;
@@ -190,6 +227,11 @@ meta_display_open (const char *name)
XCreateSimpleWindow (display->xdisplay,
((MetaScreen*)display->screens->data)->xroot,
-100, -100, 1, 1, 0, 0, 0);
+
+ set_string_hint (display,
+ display->leader_window,
+ display->atom_net_supporting_wm_check,
+ "Metacity");
/* Now manage all existing windows */
tmp = display->screens;
@@ -560,7 +602,39 @@ event_queue_callback (MetaEventQueue *queue,
break;
case ClientMessage:
if (window)
- meta_window_client_message (window, event);
+ {
+ meta_window_client_message (window, event);
+ }
+ else
+ {
+ MetaScreen *screen;
+
+ screen = meta_display_screen_for_root (display,
+ event->xclient.window);
+
+ if (screen &&
+ event->xclient.message_type ==
+ display->atom_net_current_desktop)
+ {
+ int space;
+ MetaWorkspace *workspace;
+
+ space = event->xclient.data.l[0];
+
+ meta_verbose ("Request to change current workspace to %d\n",
+ space);
+
+ workspace =
+ meta_display_get_workspace_by_screen_index (display,
+ screen,
+ space);
+
+ if (workspace)
+ meta_workspace_activate (workspace);
+ else
+ meta_verbose ("Don't know about workspace %d\n", space);
+ }
+ }
break;
case MappingNotify:
break;
diff --git a/src/display.h b/src/display.h
index e1704ce..553360d 100644
--- a/src/display.h
+++ b/src/display.h
@@ -62,6 +62,17 @@ struct _MetaDisplay
Atom atom_sm_client_id;
Atom atom_wm_client_leader;
Atom atom_wm_window_role;
+ Atom atom_net_current_desktop;
+ Atom atom_net_supporting_wm_check;
+ Atom atom_net_wm_supported;
+ Atom atom_net_wm_window_type;
+ Atom atom_net_wm_window_type_desktop;
+ Atom atom_net_wm_window_type_dock;
+ Atom atom_net_wm_window_type_toolbar;
+ Atom atom_net_wm_window_type_menu;
+ Atom atom_net_wm_window_type_dialog;
+ Atom atom_net_wm_window_type_normal;
+ Atom atom_net_wm_state_modal;
/* This is the actual window from focus events,
* not the one we last set
diff --git a/src/frame.c b/src/frame.c
index 9ec4734..4e9d0bb 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -52,14 +52,19 @@ meta_frame_init_info (MetaFrame *frame,
{
info->flags =
META_FRAME_ALLOWS_MENU | META_FRAME_ALLOWS_DELETE |
- META_FRAME_ALLOWS_ICONIFY | META_FRAME_ALLOWS_MAXIMIZE |
META_FRAME_ALLOWS_RESIZE;
+ if (frame->window->type == META_WINDOW_NORMAL)
+ info->flags |= (META_FRAME_ALLOWS_ICONIFY | META_FRAME_ALLOWS_MAXIMIZE);
+
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;
@@ -257,6 +262,8 @@ meta_window_ensure_frame (MetaWindow *window)
frame->right_width = 0;
frame->bg_pixel = 0;
+ frame->mapped = FALSE;
+
attrs.event_mask = EVENT_MASK;
frame->xwindow = XCreateWindow (window->display->xdisplay,
@@ -355,19 +362,37 @@ meta_window_destroy_frame (MetaWindow *window)
}
void
-meta_frame_sync_to_window (MetaFrame *frame)
+meta_frame_sync_to_window (MetaFrame *frame,
+ gboolean need_move,
+ gboolean need_resize)
{
meta_verbose ("Syncing frame geometry %d,%d %dx%d pixel %ld\n",
frame->rect.x, frame->rect.y,
frame->rect.width, frame->rect.height,
frame->bg_pixel);
+
+ /* set bg to none to avoid flicker */
set_background_none (frame);
- XMoveResizeWindow (frame->window->display->xdisplay,
- frame->xwindow,
- frame->rect.x,
- frame->rect.y,
- frame->rect.width,
- frame->rect.height);
+
+ if (need_move && need_resize)
+ XMoveResizeWindow (frame->window->display->xdisplay,
+ frame->xwindow,
+ frame->rect.x,
+ frame->rect.y,
+ frame->rect.width,
+ frame->rect.height);
+ else if (need_move)
+ XMoveWindow (frame->window->display->xdisplay,
+ frame->xwindow,
+ frame->rect.x,
+ frame->rect.y);
+ else if (need_resize)
+ 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);
}
@@ -703,6 +728,11 @@ get_menu_items (MetaFrame *frame,
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))
diff --git a/src/frame.h b/src/frame.h
index 1e3e52b..4947142 100644
--- a/src/frame.h
+++ b/src/frame.h
@@ -62,6 +62,7 @@ struct _MetaFrame
guint tooltip_timeout;
guint theme_acquired : 1;
+ guint mapped : 1;
};
void meta_window_ensure_frame (MetaWindow *window);
@@ -84,7 +85,9 @@ void meta_frame_adjust_for_gravity (int win_gravity,
int y,
int *win_root_x,
int *win_root_y);
-void meta_frame_sync_to_window (MetaFrame *frame);
+void meta_frame_sync_to_window (MetaFrame *frame,
+ gboolean need_move,
+ gboolean need_resize);
#endif
diff --git a/src/menu.c b/src/menu.c
index f9687a7..1cb4f97 100644
--- a/src/menu.c
+++ b/src/menu.c
@@ -54,7 +54,10 @@ static MenuItem menuitems[] = {
{ META_MESSAGE_MENU_MAXIMIZE, NULL, N_("Ma_ximize") },
{ META_MESSAGE_MENU_UNMAXIMIZE, NULL, N_("_Unmaximize") },
{ META_MESSAGE_MENU_SHADE, NULL, N_("_Shade") },
- { META_MESSAGE_MENU_UNSHADE, NULL, N_("U_nshade") }
+ { META_MESSAGE_MENU_UNSHADE, NULL, N_("U_nshade") },
+ { 0, NULL, NULL }, /* separator */
+ { META_MESSAGE_MENU_STICK, NULL, N_("Put on _All Workspaces") },
+ { META_MESSAGE_MENU_UNSTICK, NULL, N_("Only on _This Workspace") }
};
static void
@@ -105,6 +108,32 @@ get_num_desktops (void)
return result;
}
+static gint
+get_active_desktop (void)
+{
+ Atom type;
+ gint format;
+ gulong nitems;
+ gulong bytes_after;
+ gulong *num;
+ int result;
+
+ XGetWindowProperty (gdk_display, gdk_root_window,
+ gdk_atom_intern ("_NET_CURRENT_DESKTOP", FALSE),
+ 0, G_MAXLONG,
+ False, XA_CARDINAL, &type, &format, &nitems,
+ &bytes_after, (guchar **)&num);
+
+ if (type != XA_CARDINAL)
+ return 0;
+
+ result = *num;
+
+ XFree (num);
+
+ return result;
+}
+
static gulong
get_current_desktop (GdkWindow *window)
{
@@ -130,7 +159,7 @@ get_current_desktop (GdkWindow *window)
if (type != XA_CARDINAL)
{
meta_ui_warning ("_NET_WM_DESKTOP has wrong type %s\n", gdk_atom_name (type));
- return -1;
+ return 0xFFFFFFFF; /* sticky */
}
result = *num;
@@ -172,40 +201,47 @@ meta_window_menu_show (gulong xwindow,
i = 0;
while (i < G_N_ELEMENTS (menuitems))
{
- if (ops & menuitems[i].op)
+ if (ops & menuitems[i].op || menuitems[i].op == 0)
{
GtkWidget *mi;
MenuData *md;
-
- if (menuitems[i].stock_id)
+
+ if (menuitems[i].op == 0)
{
- GtkWidget *image;
-
- mi = gtk_image_menu_item_new_with_mnemonic (menuitems[i].label);
- image = gtk_image_new_from_stock (menuitems[i].stock_id,
- GTK_ICON_SIZE_MENU);
- gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (mi),
- image);
- gtk_widget_show (image);
+ mi = gtk_separator_menu_item_new ();
}
else
{
- mi = gtk_menu_item_new_with_mnemonic (menuitems[i].label);
+ if (menuitems[i].stock_id)
+ {
+ GtkWidget *image;
+
+ mi = gtk_image_menu_item_new_with_mnemonic (menuitems[i].label);
+ image = gtk_image_new_from_stock (menuitems[i].stock_id,
+ GTK_ICON_SIZE_MENU);
+ gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (mi),
+ image);
+ gtk_widget_show (image);
+ }
+ else
+ {
+ mi = gtk_menu_item_new_with_mnemonic (menuitems[i].label);
+ }
+
+ if (insensitive & menuitems[i].op)
+ gtk_widget_set_sensitive (mi, FALSE);
+
+ md = g_new (MenuData, 1);
+
+ md->window = window;
+ md->op = menuitems[i].op;
+
+ gtk_signal_connect (GTK_OBJECT (mi),
+ "activate",
+ GTK_SIGNAL_FUNC (activate_cb),
+ md);
}
-
- if (insensitive & menuitems[i].op)
- gtk_widget_set_sensitive (mi, FALSE);
-
- md = g_new (MenuData, 1);
-
- md->window = window;
- md->op = menuitems[i].op;
- gtk_signal_connect (GTK_OBJECT (mi),
- "activate",
- GTK_SIGNAL_FUNC (activate_cb),
- md);
-
gtk_menu_shell_append (GTK_MENU_SHELL (menu),
mi);
@@ -222,22 +258,22 @@ meta_window_menu_show (gulong xwindow,
meta_ui_warning ("Creating %d workspace menu current %d\n",
n_workspaces, current_workspace);
- if (n_workspaces > 0 && current_workspace >= 0)
+ if (n_workspaces > 0)
{
GtkWidget *mi;
-
- mi = gtk_separator_menu_item_new ();
- gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
- gtk_widget_show (mi);
i = 0;
while (i < n_workspaces)
{
char *label;
MenuData *md;
-
- label = g_strdup_printf (_("Move to workspace _%d\n"),
- i + 1);
+
+ if (current_workspace == 0xFFFFFFFF)
+ label = g_strdup_printf (_("Only on workspace _%d\n"),
+ i + 1);
+ else
+ label = g_strdup_printf (_("Move to workspace _%d\n"),
+ i + 1);
mi = gtk_menu_item_new_with_mnemonic (label);
@@ -429,6 +465,14 @@ activate_cb (GtkWidget *menuitem, gpointer data)
wmspec_change_desktop (md->window, workspace);
}
break;
+
+ case META_MESSAGE_MENU_STICK:
+ wmspec_change_desktop (md->window, 0xFFFFFFFF);
+ break;
+
+ case META_MESSAGE_MENU_UNSTICK:
+ wmspec_change_desktop (md->window, get_active_desktop ());
+ break;
default:
meta_ui_warning (G_STRLOC": Unknown window op\n");
diff --git a/src/screen.c b/src/screen.c
index 75851c6..5b8f5c3 100644
--- a/src/screen.c
+++ b/src/screen.c
@@ -30,6 +30,7 @@
#include "keybindings.h"
#include <X11/cursorfont.h>
+#include <X11/Xatom.h>
#include <locale.h>
#include <string.h>
@@ -40,6 +41,53 @@ static char* get_screen_name (MetaDisplay *display,
int number);
+static int
+set_wm_check_hint (MetaScreen *screen)
+{
+ unsigned long data[1];
+
+ data[0] = screen->display->leader_window;
+
+ XChangeProperty (screen->display->xdisplay, screen->xroot,
+ screen->display->atom_net_supporting_wm_check,
+ XA_WINDOW,
+ 32, PropModeReplace, (guchar*) data, 1);
+ return Success;
+}
+
+static int
+set_supported_hint (MetaScreen *screen)
+{
+#define N_SUPPORTED 17
+ Atom atoms[N_SUPPORTED];
+
+ atoms[0] = screen->display->atom_net_wm_name;
+ atoms[1] = screen->display->atom_net_close_window;
+ atoms[2] = screen->display->atom_net_wm_state;
+ atoms[3] = screen->display->atom_net_wm_state_shaded;
+ atoms[4] = screen->display->atom_net_wm_state_maximized_vert;
+ atoms[5] = screen->display->atom_net_wm_state_maximized_horz;
+ atoms[6] = screen->display->atom_net_wm_desktop;
+ atoms[7] = screen->display->atom_net_number_of_desktops;
+ atoms[8] = screen->display->atom_net_current_desktop;
+ atoms[9] = screen->display->atom_net_wm_window_type;
+ atoms[10] = screen->display->atom_net_wm_window_type_desktop;
+ atoms[11] = screen->display->atom_net_wm_window_type_dock;
+ atoms[12] = screen->display->atom_net_wm_window_type_toolbar;
+ atoms[13] = screen->display->atom_net_wm_window_type_menu;
+ atoms[14] = screen->display->atom_net_wm_window_type_dialog;
+ atoms[15] = screen->display->atom_net_wm_window_type_normal;
+ atoms[16] = screen->display->atom_net_wm_state_modal;
+
+ XChangeProperty (screen->display->xdisplay, screen->xroot,
+ screen->display->atom_net_wm_supported,
+ XA_ATOM,
+ 32, PropModeReplace, (guchar*) atoms, N_SUPPORTED);
+
+ return Success;
+#undef N_SUPPORTED
+}
+
MetaScreen*
meta_screen_new (MetaDisplay *display,
int number)
@@ -104,6 +152,10 @@ meta_screen_new (MetaDisplay *display,
screen->showing_tooltip = FALSE;
+ set_supported_hint (screen);
+
+ set_wm_check_hint (screen);
+
/* Screens must have at least one workspace at all times,
* so create that required workspace.
*/
diff --git a/src/screen.h b/src/screen.h
index 398ca15..89c7130 100644
--- a/src/screen.h
+++ b/src/screen.h
@@ -51,8 +51,6 @@ struct _MetaScreen
guint showing_tooltip : 1;
- /*< private >*/
-
/* we only need one since we only draw to a single visual (that of
* root window)
*/
diff --git a/src/theme.c b/src/theme.c
index eb37437..11f911e 100644
--- a/src/theme.c
+++ b/src/theme.c
@@ -179,10 +179,10 @@ default_release_frame (MetaFrameInfo *info,
#define SPACER_SPACING 3
#define SPACER_WIDTH 2
#define SPACER_HEIGHT 10
-#define BUTTON_WIDTH 12
-#define BUTTON_HEIGHT 12
-#define BUTTON_PAD 2
-#define INNER_BUTTON_PAD 1
+#define BUTTON_WIDTH 14
+#define BUTTON_HEIGHT 14
+#define BUTTON_PAD 1
+#define INNER_BUTTON_PAD 3
static void
calc_geometry (MetaFrameInfo *info,
DefaultFrameData *d,
diff --git a/src/theme.h b/src/theme.h
index a80147a..37c46ab 100644
--- a/src/theme.h
+++ b/src/theme.h
@@ -42,7 +42,8 @@ typedef enum
META_FRAME_ALLOWS_RESIZE = 1 << 4,
META_FRAME_TRANSIENT = 1 << 5,
META_FRAME_HAS_FOCUS = 1 << 6,
- META_FRAME_SHADED = 1 << 7
+ META_FRAME_SHADED = 1 << 7,
+ META_FRAME_STUCK = 1 << 8
} MetaFrameFlags;
typedef enum
diff --git a/src/uislave/menu.c b/src/uislave/menu.c
index f9687a7..1cb4f97 100644
--- a/src/uislave/menu.c
+++ b/src/uislave/menu.c
@@ -54,7 +54,10 @@ static MenuItem menuitems[] = {
{ META_MESSAGE_MENU_MAXIMIZE, NULL, N_("Ma_ximize") },
{ META_MESSAGE_MENU_UNMAXIMIZE, NULL, N_("_Unmaximize") },
{ META_MESSAGE_MENU_SHADE, NULL, N_("_Shade") },
- { META_MESSAGE_MENU_UNSHADE, NULL, N_("U_nshade") }
+ { META_MESSAGE_MENU_UNSHADE, NULL, N_("U_nshade") },
+ { 0, NULL, NULL }, /* separator */
+ { META_MESSAGE_MENU_STICK, NULL, N_("Put on _All Workspaces") },
+ { META_MESSAGE_MENU_UNSTICK, NULL, N_("Only on _This Workspace") }
};
static void
@@ -105,6 +108,32 @@ get_num_desktops (void)
return result;
}
+static gint
+get_active_desktop (void)
+{
+ Atom type;
+ gint format;
+ gulong nitems;
+ gulong bytes_after;
+ gulong *num;
+ int result;
+
+ XGetWindowProperty (gdk_display, gdk_root_window,
+ gdk_atom_intern ("_NET_CURRENT_DESKTOP", FALSE),
+ 0, G_MAXLONG,
+ False, XA_CARDINAL, &type, &format, &nitems,
+ &bytes_after, (guchar **)&num);
+
+ if (type != XA_CARDINAL)
+ return 0;
+
+ result = *num;
+
+ XFree (num);
+
+ return result;
+}
+
static gulong
get_current_desktop (GdkWindow *window)
{
@@ -130,7 +159,7 @@ get_current_desktop (GdkWindow *window)
if (type != XA_CARDINAL)
{
meta_ui_warning ("_NET_WM_DESKTOP has wrong type %s\n", gdk_atom_name (type));
- return -1;
+ return 0xFFFFFFFF; /* sticky */
}
result = *num;
@@ -172,40 +201,47 @@ meta_window_menu_show (gulong xwindow,
i = 0;
while (i < G_N_ELEMENTS (menuitems))
{
- if (ops & menuitems[i].op)
+ if (ops & menuitems[i].op || menuitems[i].op == 0)
{
GtkWidget *mi;
MenuData *md;
-
- if (menuitems[i].stock_id)
+
+ if (menuitems[i].op == 0)
{
- GtkWidget *image;
-
- mi = gtk_image_menu_item_new_with_mnemonic (menuitems[i].label);
- image = gtk_image_new_from_stock (menuitems[i].stock_id,
- GTK_ICON_SIZE_MENU);
- gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (mi),
- image);
- gtk_widget_show (image);
+ mi = gtk_separator_menu_item_new ();
}
else
{
- mi = gtk_menu_item_new_with_mnemonic (menuitems[i].label);
+ if (menuitems[i].stock_id)
+ {
+ GtkWidget *image;
+
+ mi = gtk_image_menu_item_new_with_mnemonic (menuitems[i].label);
+ image = gtk_image_new_from_stock (menuitems[i].stock_id,
+ GTK_ICON_SIZE_MENU);
+ gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (mi),
+ image);
+ gtk_widget_show (image);
+ }
+ else
+ {
+ mi = gtk_menu_item_new_with_mnemonic (menuitems[i].label);
+ }
+
+ if (insensitive & menuitems[i].op)
+ gtk_widget_set_sensitive (mi, FALSE);
+
+ md = g_new (MenuData, 1);
+
+ md->window = window;
+ md->op = menuitems[i].op;
+
+ gtk_signal_connect (GTK_OBJECT (mi),
+ "activate",
+ GTK_SIGNAL_FUNC (activate_cb),
+ md);
}
-
- if (insensitive & menuitems[i].op)
- gtk_widget_set_sensitive (mi, FALSE);
-
- md = g_new (MenuData, 1);
-
- md->window = window;
- md->op = menuitems[i].op;
- gtk_signal_connect (GTK_OBJECT (mi),
- "activate",
- GTK_SIGNAL_FUNC (activate_cb),
- md);
-
gtk_menu_shell_append (GTK_MENU_SHELL (menu),
mi);
@@ -222,22 +258,22 @@ meta_window_menu_show (gulong xwindow,
meta_ui_warning ("Creating %d workspace menu current %d\n",
n_workspaces, current_workspace);
- if (n_workspaces > 0 && current_workspace >= 0)
+ if (n_workspaces > 0)
{
GtkWidget *mi;
-
- mi = gtk_separator_menu_item_new ();
- gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
- gtk_widget_show (mi);
i = 0;
while (i < n_workspaces)
{
char *label;
MenuData *md;
-
- label = g_strdup_printf (_("Move to workspace _%d\n"),
- i + 1);
+
+ if (current_workspace == 0xFFFFFFFF)
+ label = g_strdup_printf (_("Only on workspace _%d\n"),
+ i + 1);
+ else
+ label = g_strdup_printf (_("Move to workspace _%d\n"),
+ i + 1);
mi = gtk_menu_item_new_with_mnemonic (label);
@@ -429,6 +465,14 @@ activate_cb (GtkWidget *menuitem, gpointer data)
wmspec_change_desktop (md->window, workspace);
}
break;
+
+ case META_MESSAGE_MENU_STICK:
+ wmspec_change_desktop (md->window, 0xFFFFFFFF);
+ break;
+
+ case META_MESSAGE_MENU_UNSTICK:
+ wmspec_change_desktop (md->window, get_active_desktop ());
+ break;
default:
meta_ui_warning (G_STRLOC": Unknown window op\n");
diff --git a/src/uislave/messages.h b/src/uislave/messages.h
index 1520386..f9a2149 100644
--- a/src/uislave/messages.h
+++ b/src/uislave/messages.h
@@ -136,7 +136,9 @@ typedef enum
META_MESSAGE_MENU_MAXIMIZE = 1 << 3,
META_MESSAGE_MENU_UNSHADE = 1 << 4,
META_MESSAGE_MENU_SHADE = 1 << 5,
- META_MESSAGE_MENU_WORKSPACES = 1 << 6
+ META_MESSAGE_MENU_UNSTICK = 1 << 6,
+ META_MESSAGE_MENU_STICK = 1 << 7,
+ META_MESSAGE_MENU_WORKSPACES = 1 << 8
} MetaMessageWindowMenuOps;
struct _MetaMessageShowWindowMenu
diff --git a/src/window.c b/src/window.c
index 9094fc1..7abdf84 100644
--- a/src/window.c
+++ b/src/window.c
@@ -49,6 +49,8 @@ static int update_wm_class (MetaWindow *window);
static int update_transient_for (MetaWindow *window);
static void update_sm_hints (MetaWindow *window);
static int update_role (MetaWindow *window);
+static int update_net_wm_type (MetaWindow *window);
+static void recalc_window_type (MetaWindow *window);
static int set_wm_state (MetaWindow *window,
int state);
static void send_configure_notify (MetaWindow *window);
@@ -64,8 +66,6 @@ static void meta_window_show (MetaWindow *window);
static void meta_window_hide (MetaWindow *window);
static void meta_window_move_resize_internal (MetaWindow *window,
- gboolean move,
- gboolean resize,
gboolean is_configure_request,
int root_x_nw,
int root_y_nw,
@@ -164,6 +164,7 @@ meta_window_new (MetaDisplay *display, Window xwindow)
window->has_focus = FALSE;
window->maximized = FALSE;
+ window->on_all_workspaces = FALSE;
window->shaded = FALSE;
window->initially_iconic = FALSE;
window->minimized = FALSE;
@@ -175,6 +176,8 @@ meta_window_new (MetaDisplay *display, Window xwindow)
window->has_minimize_func = TRUE;
window->has_maximize_func = TRUE;
+ window->wm_state_modal = FALSE;
+
window->res_class = NULL;
window->res_name = NULL;
window->role = NULL;
@@ -183,6 +186,9 @@ meta_window_new (MetaDisplay *display, Window xwindow)
window->xtransient_for = None;
window->xgroup_leader = None;
window->xclient_leader = None;
+
+ window->type = META_WINDOW_NORMAL;
+ window->type_atom = None;
meta_display_register_x_window (display, &window->xwindow, window);
@@ -196,6 +202,7 @@ meta_window_new (MetaDisplay *display, Window xwindow)
update_transient_for (window);
update_sm_hints (window); /* must come after transient_for */
update_role (window);
+ update_net_wm_type (window);
if (window->initially_iconic)
{
@@ -218,7 +225,7 @@ meta_window_new (MetaDisplay *display, Window xwindow)
* passing TRUE for is_configure_request, ICCCM says
* initial map is handled same as configure request
*/
- meta_window_move_resize_internal (window, TRUE, TRUE, TRUE,
+ meta_window_move_resize_internal (window, TRUE,
window->size_hints.x,
window->size_hints.y,
window->size_hints.width,
@@ -308,6 +315,12 @@ meta_window_calc_showing (MetaWindow *window)
meta_verbose ("Window %s is on the active workspace %d\n",
window->desc,
meta_workspace_index (window->screen->active_workspace));
+
+ if (window->on_all_workspaces)
+ {
+ on_workspace = TRUE;
+ meta_verbose ("Window %s is on all workspaces\n", window->desc);
+ }
if (window->minimized || !on_workspace)
{
@@ -334,16 +347,24 @@ meta_window_show (MetaWindow *window)
/* Shaded means the frame is mapped but the window is not */
- if (window->frame)
- XMapWindow (window->display->xdisplay, window->frame->xwindow);
+ if (window->frame && !window->frame->mapped)
+ {
+ meta_verbose ("Frame actually needs map\n");
+ window->frame->mapped = TRUE;
+ XMapWindow (window->display->xdisplay, window->frame->xwindow);
+ }
if (window->shaded)
{
- window->mapped = FALSE;
- meta_error_trap_push (window->display);
- XUnmapWindow (window->display->xdisplay, window->xwindow);
- meta_error_trap_pop (window->display);
-
+ if (window->mapped)
+ {
+ meta_verbose ("%s actually needs unmap\n", window->desc);
+ window->mapped = FALSE;
+ meta_error_trap_push (window->display);
+ XUnmapWindow (window->display->xdisplay, window->xwindow);
+ meta_error_trap_pop (window->display);
+ }
+
if (!window->iconic)
{
window->iconic = TRUE;
@@ -352,10 +373,14 @@ meta_window_show (MetaWindow *window)
}
else
{
- window->mapped = TRUE;
- meta_error_trap_push (window->display);
- XMapWindow (window->display->xdisplay, window->xwindow);
- meta_error_trap_pop (window->display);
+ if (!window->mapped)
+ {
+ meta_verbose ("%s actually needs map\n", window->desc);
+ window->mapped = TRUE;
+ meta_error_trap_push (window->display);
+ XMapWindow (window->display->xdisplay, window->xwindow);
+ meta_error_trap_pop (window->display);
+ }
if (window->iconic)
{
@@ -370,11 +395,19 @@ 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);
+ if (window->frame && window->frame->mapped)
+ {
+ meta_verbose ("Frame actually needs unmap\n");
+ window->frame->mapped = FALSE;
+ XUnmapWindow (window->display->xdisplay, window->frame->xwindow);
+ }
- window->mapped = FALSE;
+ if (window->mapped)
+ {
+ meta_verbose ("%s actually needs unmap\n", window->desc);
+ window->mapped = FALSE;
+ XUnmapWindow (window->display->xdisplay, window->xwindow);
+ }
if (!window->iconic)
{
@@ -466,8 +499,6 @@ meta_window_unshade (MetaWindow *window)
static void
meta_window_move_resize_internal (MetaWindow *window,
- gboolean move,
- gboolean resize,
gboolean is_configure_request,
int root_x_nw,
int root_y_nw,
@@ -478,31 +509,24 @@ meta_window_move_resize_internal (MetaWindow *window,
unsigned int mask;
gboolean need_configure_notify;
MetaFrameGeometry fgeom;
+ gboolean need_move_client = FALSE;
+ gboolean need_move_frame = FALSE;
+ gboolean need_resize_client = FALSE;
+ gboolean need_resize_frame = FALSE;
- if (resize)
- meta_verbose ("Resizing %s to %d x %d\n", window->desc, w, h);
- if (move)
- meta_verbose ("Moving %s to %d,%d\n", window->desc,
- root_x_nw, root_y_nw);
-
+ meta_verbose ("Move/resize %s to %d,%d %dx%d\n",
+ window->desc, root_x_nw, root_y_nw, w, h);
+ constrain_size (window, w, h, &w, &h);
+ meta_verbose ("Constrained resize of %s to %d x %d\n", window->desc, w, h);
+
+ if (w != window->rect.width ||
+ h != window->rect.height)
+ need_resize_client = TRUE;
- /* remember that root_x_nw, root_y_nw are bogus if not moving,
- * and w, h are bogus if not resizing
- */
+ window->rect.width = w;
+ window->rect.height = h;
- if (resize)
- {
- constrain_size (window, w, h, &w, &h);
- meta_verbose ("Constrained resize of %s to %d x %d\n", window->desc, w, h);
- if (w == window->rect.width &&
- h == window->rect.height)
- resize = FALSE;
-
- window->rect.width = w;
- window->rect.height = h;
- }
-
if (window->frame)
{
int new_w, new_h;
@@ -519,7 +543,9 @@ meta_window_move_resize_internal (MetaWindow *window,
else
new_h = window->rect.height + fgeom.top_height + fgeom.bottom_height;
- /* FIXME could check to avoid XResizeWindow on frame */
+ if (new_w != window->frame->rect.width ||
+ new_h != window->frame->rect.height)
+ need_resize_frame = TRUE;
window->frame->rect.width = new_w;
window->frame->rect.height = new_h;
@@ -527,11 +553,8 @@ meta_window_move_resize_internal (MetaWindow *window,
meta_verbose ("Calculated frame size %dx%d\n",
window->frame->rect.width,
window->frame->rect.height);
- }
-
- if (move)
- {
- if (is_configure_request && window->frame)
+
+ if (is_configure_request)
{
meta_frame_adjust_for_gravity (window->size_hints.win_gravity,
window->frame->rect.width,
@@ -541,50 +564,52 @@ meta_window_move_resize_internal (MetaWindow *window,
root_y_nw,
&root_x_nw,
&root_y_nw);
-
+
meta_verbose ("Compensated position for gravity, new pos %d,%d\n",
root_x_nw, root_y_nw);
}
+ }
- constrain_position (window,
- window->frame ? &fgeom : NULL,
- root_x_nw, root_y_nw,
- &root_x_nw, &root_y_nw);
+ constrain_position (window,
+ window->frame ? &fgeom : NULL,
+ root_x_nw, root_y_nw,
+ &root_x_nw, &root_y_nw);
- meta_verbose ("Constrained position to %d,%d\n",
- root_x_nw, root_y_nw);
+ meta_verbose ("Constrained position to %d,%d\n",
+ root_x_nw, root_y_nw);
- if (window->frame)
- {
- int new_x, new_y;
-
- new_x = root_x_nw - fgeom.left_width;
- new_y = root_y_nw - fgeom.top_height;
+ if (window->frame)
+ {
+ int new_x, new_y;
- if (new_x == window->frame->rect.x &&
- new_y == window->frame->rect.y &&
- window->rect.x == fgeom.left_width &&
- window->rect.y == fgeom.top_height)
- move = FALSE;
-
- window->frame->rect.x = new_x;
- window->frame->rect.y = new_y;
-
- /* window->rect.x, window->rect.y are relative to frame,
- * remember they are the server coords
- */
- window->rect.x = fgeom.left_width;
- window->rect.y = fgeom.top_height;
- }
- else
- {
- if (root_x_nw == window->rect.x &&
- root_y_nw == window->rect.y)
- move = FALSE;
+ new_x = root_x_nw - fgeom.left_width;
+ new_y = root_y_nw - fgeom.top_height;
- window->rect.x = root_x_nw;
- window->rect.y = root_y_nw;
- }
+ if (new_x != window->frame->rect.x ||
+ new_y != window->frame->rect.y)
+ need_move_frame = TRUE;
+
+ if (window->rect.x != fgeom.left_width ||
+ window->rect.y != fgeom.top_height)
+ need_move_client = TRUE;
+
+ window->frame->rect.x = new_x;
+ window->frame->rect.y = new_y;
+
+ /* window->rect.x, window->rect.y are relative to frame,
+ * remember they are the server coords
+ */
+ window->rect.x = fgeom.left_width;
+ window->rect.y = fgeom.top_height;
+ }
+ else
+ {
+ if (root_x_nw != window->rect.x ||
+ root_y_nw != window->rect.y)
+ need_move_client = TRUE;
+
+ window->rect.x = root_x_nw;
+ window->rect.y = root_y_nw;
}
/* Fill in other frame member variables */
@@ -602,8 +627,11 @@ meta_window_move_resize_internal (MetaWindow *window,
* notify if we don't resize. ICCCM 4.1.5
*/
need_configure_notify =
- (!resize) ||
- (is_configure_request && !(move || resize || window->border_width != 0));
+ (!need_resize_client) ||
+ (is_configure_request &&
+ !(need_move_client || need_move_frame ||
+ need_resize_client || need_resize_frame ||
+ window->border_width != 0));
/* Sync our new size/pos with X as efficiently as possible */
@@ -616,17 +644,17 @@ meta_window_move_resize_internal (MetaWindow *window,
mask = 0;
if (is_configure_request && window->border_width != 0)
mask |= CWBorderWidth; /* must force to 0 */
- if (move)
+ if (need_move_client)
mask |= (CWX | CWY);
- if (resize)
+ if (need_resize_client)
mask |= (CWWidth | CWHeight);
if (mask != 0)
{
meta_verbose ("Syncing new geometry to client, border: %s pos: %s size: %s\n",
mask & CWBorderWidth ? "true" : "false",
- mask & CWX ? "true" : "false",
- mask & CWWidth ? "true" : "false");
+ need_move_client ? "true" : "false",
+ need_resize_client ? "true" : "false");
meta_error_trap_push (window->display);
XConfigureWindow (window->display->xdisplay,
@@ -638,10 +666,16 @@ meta_window_move_resize_internal (MetaWindow *window,
/* Now do the frame */
if (window->frame)
- meta_frame_sync_to_window (window->frame);
+ meta_frame_sync_to_window (window->frame, need_move_frame, need_resize_frame);
if (need_configure_notify)
send_configure_notify (window);
+
+ /* Invariants leaving this function are:
+ * a) window->rect and frame->rect reflect the actual
+ * server-side size/pos of window->xwindow and frame->xwindow
+ * b) all constraints are obeyed by window->rect and frame->rect
+ */
}
void
@@ -649,7 +683,11 @@ meta_window_resize (MetaWindow *window,
int w,
int h)
{
- meta_window_move_resize_internal (window, FALSE, TRUE, FALSE, -1, -1, w, h);
+ int x, y;
+
+ meta_window_get_position (window, &x, &y);
+
+ meta_window_move_resize_internal (window, FALSE, x, y, w, h);
}
void
@@ -657,8 +695,10 @@ meta_window_move (MetaWindow *window,
int root_x_nw,
int root_y_nw)
{
- meta_window_move_resize_internal (window, TRUE, FALSE, FALSE,
- root_x_nw, root_y_nw, -1, -1);
+ meta_window_move_resize_internal (window, FALSE,
+ root_x_nw, root_y_nw,
+ window->rect.width,
+ window->rect.height);
}
void
@@ -668,7 +708,7 @@ meta_window_move_resize (MetaWindow *window,
int w,
int h)
{
- meta_window_move_resize_internal (window, TRUE, TRUE, FALSE,
+ meta_window_move_resize_internal (window, FALSE,
root_x_nw, root_y_nw,
w, h);
}
@@ -676,7 +716,7 @@ meta_window_move_resize (MetaWindow *window,
void
meta_window_queue_move_resize (MetaWindow *window)
{
- /* FIXME actually queue */
+ /* FIXME actually queue, don't do it immediately */
int x, y;
meta_window_get_position (window, &x, &y);
@@ -779,6 +819,75 @@ meta_window_change_workspace (MetaWindow *window,
}
void
+meta_window_stick (MetaWindow *window)
+{
+ if (window->on_all_workspaces)
+ return;
+
+ /* We don't change window->workspaces, because we revert
+ * to that original workspace list if on_all_workspaces is
+ * toggled back off.
+ */
+ window->on_all_workspaces = TRUE;
+
+ meta_window_set_current_workspace_hint (window);
+
+ meta_window_queue_calc_showing (window);
+}
+
+void
+meta_window_unstick (MetaWindow *window)
+{
+ if (!window->on_all_workspaces)
+ return;
+
+ /* Revert to window->workspaces */
+
+ window->on_all_workspaces = FALSE;
+
+ /* We change ourselves to the active workspace, since otherwise you'd get
+ * a weird window-vaporization effect. Once we have UI for being
+ * on more than one workspace this should probably be add_workspace
+ * not change_workspace.
+ */
+ if (!meta_workspace_contains_window (window->screen->active_workspace,
+ window))
+ meta_window_change_workspace (window, window->screen->active_workspace);
+
+ meta_window_set_current_workspace_hint (window);
+
+ meta_window_queue_calc_showing (window);
+}
+
+int
+meta_window_set_current_workspace_hint (MetaWindow *window)
+{
+ /* FIXME if on more than one workspace, we claim to be "sticky",
+ * the WM spec doesn't say what to do here.
+ */
+ unsigned long data[1];
+
+ if (window->workspaces == NULL)
+ return Success; /* this happens when destroying windows */
+
+ if (window->on_all_workspaces ||
+ g_list_length (window->workspaces) > 1)
+ data[0] = 0xFFFFFFFF;
+ else
+ data[0] = meta_workspace_screen_index (window->workspaces->data);
+
+ meta_verbose ("Setting _NET_WM_DESKTOP of %s to %ld\n",
+ window->desc, data[0]);
+
+ meta_error_trap_push (window->display);
+ XChangeProperty (window->display->xdisplay, window->xwindow,
+ window->display->atom_net_wm_desktop,
+ XA_CARDINAL,
+ 32, PropModeReplace, (guchar*) data, 1);
+ return meta_error_trap_pop (window->display);
+}
+
+void
meta_window_raise (MetaWindow *window)
{
meta_verbose ("Raising window %s\n", window->desc);
@@ -891,9 +1000,19 @@ meta_window_client_message (MetaWindow *window,
space);
if (workspace)
- meta_window_change_workspace (window, workspace);
+ {
+ if (window->on_all_workspaces)
+ meta_window_unstick (window);
+ meta_window_change_workspace (window, workspace);
+ }
+ else if (space == 0xFFFFFFFF)
+ {
+ meta_window_stick (window);
+ }
else
- meta_verbose ("No such workspace %d for screen\n", space);
+ {
+ meta_verbose ("No such workspace %d for screen\n", space);
+ }
return TRUE;
}
@@ -1026,7 +1145,7 @@ process_property_notify (MetaWindow *window,
else if (event->atom == XA_WM_TRANSIENT_FOR)
{
update_transient_for (window);
-
+
meta_window_queue_move_resize (window);
}
else if (event->atom ==
@@ -1041,6 +1160,11 @@ process_property_notify (MetaWindow *window,
{
meta_warning ("Broken client changed client leader window or SM client ID\n");
}
+ else if (event->atom ==
+ window->display->atom_net_wm_window_type)
+ {
+ update_net_wm_type (window);
+ }
return TRUE;
}
@@ -1109,7 +1233,7 @@ process_configure_request (MetaWindow *window,
window->size_hints.width = width;
window->size_hints.height = height;
- meta_window_move_resize_internal (window, TRUE, TRUE, TRUE,
+ meta_window_move_resize_internal (window, TRUE,
window->size_hints.x,
window->size_hints.y,
window->size_hints.width,
@@ -1427,6 +1551,7 @@ update_net_wm_state (MetaWindow *window)
window->shaded = FALSE;
window->maximized = FALSE;
+ window->wm_state_modal = FALSE;
meta_error_trap_push (window->display);
XGetWindowProperty (window->display->xdisplay, window->xwindow,
@@ -1437,10 +1562,16 @@ update_net_wm_state (MetaWindow *window)
result = meta_error_trap_pop (window->display);
if (result != Success)
- return result;
-
+ {
+ recalc_window_type (window);
+ return result;
+ }
+
if (type != XA_ATOM)
- return -1; /* whatever */
+ {
+ recalc_window_type (window);
+ return -1; /* whatever */
+ }
i = 0;
while (i < n_atoms)
@@ -1451,12 +1582,16 @@ update_net_wm_state (MetaWindow *window)
window->maximized = TRUE;
else if (atoms[i] == window->display->atom_net_wm_state_maximized_vert)
window->maximized = TRUE;
+ else if (atoms[i] == window->display->atom_net_wm_state_modal)
+ window->wm_state_modal = TRUE;
++i;
}
XFree (atoms);
+ recalc_window_type (window);
+
return Success;
}
@@ -1746,10 +1881,122 @@ update_transient_for (MetaWindow *window)
window->xtransient_for);
else
meta_verbose ("Window %s is not transient\n", window->desc);
+
+ /* may now be a dialog */
+ recalc_window_type (window);
return meta_error_trap_pop (window->display);
}
+static int
+update_net_wm_type (MetaWindow *window)
+{
+ Atom type;
+ gint format;
+ gulong n_atoms;
+ gulong bytes_after;
+ Atom *atoms;
+ int result;
+ int i;
+
+ window->type_atom = None;
+
+ meta_error_trap_push (window->display);
+ XGetWindowProperty (window->display->xdisplay, window->xwindow,
+ window->display->atom_net_wm_window_type,
+ 0, G_MAXLONG,
+ False, XA_ATOM, &type, &format, &n_atoms,
+ &bytes_after, (guchar **)&atoms);
+
+ result = meta_error_trap_pop (window->display);
+ if (result != Success)
+ {
+ recalc_window_type (window);
+ return result;
+ }
+
+ if (type != XA_ATOM)
+ {
+ recalc_window_type (window);
+ return -1; /* whatever */
+ }
+
+ i = 0;
+ while (i < n_atoms)
+ {
+ /* We break as soon as we find one we recognize,
+ * supposed to prefer those near the front of the list
+ */
+ if (atoms[i] == window->display->atom_net_wm_window_type_desktop ||
+ atoms[i] == window->display->atom_net_wm_window_type_dock ||
+ atoms[i] == window->display->atom_net_wm_window_type_toolbar ||
+ atoms[i] == window->display->atom_net_wm_window_type_menu ||
+ atoms[i] == window->display->atom_net_wm_window_type_dialog ||
+ atoms[i] == window->display->atom_net_wm_window_type_normal)
+ {
+ window->type_atom = atoms[i];
+ break;
+ }
+
+ ++i;
+ }
+
+ XFree (atoms);
+
+ if (meta_is_verbose ())
+ {
+ char *str;
+
+ meta_error_trap_push (window->display);
+ str = XGetAtomName (window->display->xdisplay, window->type_atom);
+ if (meta_error_trap_pop (window->display))
+ str = NULL;
+
+ meta_verbose ("Window %s type atom %s\n", window->desc,
+ str ? str : "(none)");
+
+ if (str)
+ XFree (str);
+ }
+
+ recalc_window_type (window);
+ return Success;
+}
+
+static void
+recalc_window_type (MetaWindow *window)
+{
+ if (window->type_atom != None)
+ {
+ if (window->type_atom == window->display->atom_net_wm_window_type_desktop)
+ window->type = META_WINDOW_DESKTOP;
+ else if (window->type_atom == window->display->atom_net_wm_window_type_dock)
+ window->type = META_WINDOW_DOCK;
+ else if (window->type_atom == window->display->atom_net_wm_window_type_toolbar)
+ window->type = META_WINDOW_TOOLBAR;
+ else if (window->type_atom == window->display->atom_net_wm_window_type_menu)
+ window->type = META_WINDOW_MENU;
+ else if (window->type_atom == window->display->atom_net_wm_window_type_dialog)
+ window->type = META_WINDOW_DIALOG;
+ else if (window->type_atom == window->display->atom_net_wm_window_type_normal)
+ window->type = META_WINDOW_NORMAL;
+ }
+ else if (window->xtransient_for != None)
+ {
+ window->type = META_WINDOW_DIALOG;
+ }
+ else
+ {
+ window->type = META_WINDOW_NORMAL;
+ }
+
+ if (window->type == META_WINDOW_DIALOG &&
+ window->wm_state_modal)
+ window->type = META_WINDOW_MODAL_DIALOG;
+
+ meta_verbose ("Calculated type %d for %s\n", window->type, window->desc);
+}
+
static void
constrain_size (MetaWindow *window,
int width, int height,
diff --git a/src/window.h b/src/window.h
index 7ee0635..237b2c1 100644
--- a/src/window.h
+++ b/src/window.h
@@ -26,6 +26,17 @@
#include "util.h"
#include <X11/Xutil.h>
+typedef enum
+{
+ META_WINDOW_NORMAL,
+ META_WINDOW_DESKTOP,
+ META_WINDOW_DOCK,
+ META_WINDOW_DIALOG,
+ META_WINDOW_MODAL_DIALOG,
+ META_WINDOW_TOOLBAR,
+ META_WINDOW_MENU
+} MetaWindowType;
+
struct _MetaWindow
{
MetaDisplay *display;
@@ -39,6 +50,9 @@ struct _MetaWindow
char *desc; /* used in debug spew */
char *title;
+ MetaWindowType type;
+ Atom type_atom;
+
/* NOTE these four are not in UTF-8, we just treat them as random
* binary data
*/
@@ -56,6 +70,12 @@ struct _MetaWindow
/* Whether we're shaded */
guint shaded : 1;
+
+ /* Whether we're sticky in the multi-workspace sense
+ * (vs. the not-scroll-with-viewport sense, we don't
+ * have no stupid viewports)
+ */
+ guint on_all_workspaces : 1;
/* Mapped is what we think the mapped state should be;
* so if we get UnmapNotify and mapped == TRUE then
@@ -88,6 +108,9 @@ struct _MetaWindow
guint has_minimize_func : 1;
guint has_maximize_func : 1;
+ /* Weird "_NET_WM_STATE_MODAL" flag */
+ guint wm_state_modal : 1;
+
/* this flag tracks receipt of focus_in focus_out and
* determines whether we draw the focus
*/
@@ -126,6 +149,8 @@ void meta_window_shade (MetaWindow *window);
void meta_window_unshade (MetaWindow *window);
void meta_window_change_workspace (MetaWindow *window,
MetaWorkspace *workspace);
+void meta_window_stick (MetaWindow *window);
+void meta_window_unstick (MetaWindow *window);
/* args to move are window pos, not frame pos */
void meta_window_move (MetaWindow *window,
@@ -167,4 +192,6 @@ gboolean meta_window_property_notify (MetaWindow *window,
XEvent *event);
gboolean meta_window_client_message (MetaWindow *window,
XEvent *event);
+
+int meta_window_set_current_workspace_hint (MetaWindow *window);
#endif
diff --git a/src/workspace.c b/src/workspace.c
index 3920c77..f7e5188 100644
--- a/src/workspace.c
+++ b/src/workspace.c
@@ -25,8 +25,8 @@
void meta_workspace_queue_calc_showing (MetaWorkspace *workspace);
-static int set_current_workspace_hint (MetaWindow *window);
static int set_number_of_spaces_hint (MetaScreen *screen);
+static int set_active_space_hint (MetaScreen *screen);
MetaWorkspace*
meta_workspace_new (MetaScreen *screen)
@@ -82,12 +82,12 @@ void
meta_workspace_add_window (MetaWorkspace *workspace,
MetaWindow *window)
{
- g_return_if_fail (g_list_find (workspace->windows, window) == NULL);
-
+ g_return_if_fail (!meta_workspace_contains_window (workspace, window));
+
workspace->windows = g_list_prepend (workspace->windows, window);
window->workspaces = g_list_prepend (window->workspaces, workspace);
- set_current_workspace_hint (window);
+ meta_window_set_current_workspace_hint (window);
meta_window_queue_calc_showing (window);
}
@@ -96,16 +96,23 @@ void
meta_workspace_remove_window (MetaWorkspace *workspace,
MetaWindow *window)
{
- g_return_if_fail (g_list_find (workspace->windows, window) != NULL);
+ g_return_if_fail (meta_workspace_contains_window (workspace, window));
workspace->windows = g_list_remove (workspace->windows, window);
window->workspaces = g_list_remove (window->workspaces, workspace);
- set_current_workspace_hint (window);
+ meta_window_set_current_workspace_hint (window);
meta_window_queue_calc_showing (window);
}
+gboolean
+meta_workspace_contains_window (MetaWorkspace *workspace,
+ MetaWindow *window)
+{
+ return g_list_find (workspace->windows, window) != NULL;
+}
+
void
meta_workspace_queue_calc_showing (MetaWorkspace *workspace)
{
@@ -135,6 +142,8 @@ meta_workspace_activate (MetaWorkspace *workspace)
workspace->screen->active_workspace = workspace;
+ set_active_space_hint (workspace->screen);
+
meta_workspace_queue_calc_showing (old);
meta_workspace_queue_calc_showing (workspace);
}
@@ -184,44 +193,35 @@ meta_workspace_screen_index (MetaWorkspace *workspace)
meta_bug ("Workspace does not exist to index!\n");
}
-
static int
-set_current_workspace_hint (MetaWindow *window)
+set_number_of_spaces_hint (MetaScreen *screen)
{
- /* if on more than one workspace, we claim to be "sticky" */
unsigned long data[1];
-
- if (window->workspaces == NULL)
- return Success; /* this happens when destroying windows */
- if (g_list_length (window->workspaces) > 1)
- data[0] = 0xFFFFFFFF;
- else
- data[0] = meta_workspace_screen_index (window->workspaces->data);
+ data[0] = meta_screen_get_n_workspaces (screen);
- meta_verbose ("Setting _NET_WM_DESKTOP of %s to %ld\n",
- window->desc, data[0]);
+ meta_verbose ("Setting _NET_NUMBER_OF_DESKTOPS to %ld\n", data[0]);
- meta_error_trap_push (window->display);
- XChangeProperty (window->display->xdisplay, window->xwindow,
- window->display->atom_net_wm_desktop,
+ meta_error_trap_push (screen->display);
+ XChangeProperty (screen->display->xdisplay, screen->xroot,
+ screen->display->atom_net_number_of_desktops,
XA_CARDINAL,
32, PropModeReplace, (guchar*) data, 1);
- return meta_error_trap_pop (window->display);
+ return meta_error_trap_pop (screen->display);
}
static int
-set_number_of_spaces_hint (MetaScreen *screen)
+set_active_space_hint (MetaScreen *screen)
{
unsigned long data[1];
- data[0] = meta_screen_get_n_workspaces (screen);
+ data[0] = meta_workspace_screen_index (screen->active_workspace);
- meta_verbose ("Setting _NET_NUMBER_OF_DESKTOPS to %ld\n", data[0]);
+ meta_verbose ("Setting _NET_CURRENT_DESKTOP to %ld\n", data[0]);
meta_error_trap_push (screen->display);
XChangeProperty (screen->display->xdisplay, screen->xroot,
- screen->display->atom_net_number_of_desktops,
+ screen->display->atom_net_current_desktop,
XA_CARDINAL,
32, PropModeReplace, (guchar*) data, 1);
return meta_error_trap_pop (screen->display);
diff --git a/src/workspace.h b/src/workspace.h
index d7f7e36..e949dd1 100644
--- a/src/workspace.h
+++ b/src/workspace.h
@@ -39,7 +39,8 @@ void meta_workspace_add_window (MetaWorkspace *workspace,
MetaWindow *window);
void meta_workspace_remove_window (MetaWorkspace *workspace,
MetaWindow *window);
-
+gboolean meta_workspace_contains_window (MetaWorkspace *workspace,
+ MetaWindow *window);
void meta_workspace_activate (MetaWorkspace *workspace);
int meta_workspace_index (MetaWorkspace *workspace);
int meta_workspace_screen_index (MetaWorkspace *workspace);