Commit b5e506ce authored by rhp's avatar rhp
Browse files

...

parent 146361b6
......@@ -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;
......
......@@ -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
......
......@@ -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))
......
......@@ -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
......
......@@ -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");
......
......@@ -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.
*/
......
......@@ -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)
*/
......
......@@ -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,
......
......@@ -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
......
......@@ -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);