2001-05-30 15:36:31 +00:00
|
|
|
/* Metacity X display handler */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
|
2001-12-09 22:41:12 +00:00
|
|
|
#include <config.h>
|
2001-05-30 15:36:31 +00:00
|
|
|
#include "display.h"
|
|
|
|
#include "util.h"
|
|
|
|
#include "main.h"
|
|
|
|
#include "screen.h"
|
|
|
|
#include "window.h"
|
2001-06-03 01:33:27 +00:00
|
|
|
#include "frame.h"
|
2001-06-04 04:58:22 +00:00
|
|
|
#include "errors.h"
|
2001-06-06 04:47:37 +00:00
|
|
|
#include "keybindings.h"
|
2001-12-10 00:38:21 +00:00
|
|
|
#include "prefs.h"
|
2001-06-06 04:47:37 +00:00
|
|
|
#include "workspace.h"
|
2001-06-10 03:17:15 +00:00
|
|
|
#include <X11/Xatom.h>
|
2001-07-26 03:14:45 +00:00
|
|
|
#include <X11/cursorfont.h>
|
2001-06-10 03:17:15 +00:00
|
|
|
#include <string.h>
|
2001-05-30 15:36:31 +00:00
|
|
|
|
2001-06-20 03:01:26 +00:00
|
|
|
#define USE_GDK_DISPLAY
|
|
|
|
|
2001-05-30 15:36:31 +00:00
|
|
|
static GSList *all_displays = NULL;
|
2001-06-03 01:33:27 +00:00
|
|
|
static void meta_spew_event (MetaDisplay *display,
|
|
|
|
XEvent *event);
|
2001-06-20 03:01:26 +00:00
|
|
|
static void event_queue_callback (XEvent *event,
|
|
|
|
gpointer data);
|
|
|
|
static gboolean event_callback (XEvent *event,
|
2001-06-03 01:33:27 +00:00
|
|
|
gpointer data);
|
|
|
|
static Window event_get_modified_window (MetaDisplay *display,
|
|
|
|
XEvent *event);
|
|
|
|
|
2001-05-30 15:36:31 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static gint
|
|
|
|
unsigned_long_equal (gconstpointer v1,
|
|
|
|
gconstpointer v2)
|
|
|
|
{
|
|
|
|
return *((const gulong*) v1) == *((const gulong*) v2);
|
|
|
|
}
|
|
|
|
|
|
|
|
static guint
|
|
|
|
unsigned_long_hash (gconstpointer v)
|
|
|
|
{
|
|
|
|
gulong val = * (const gulong *) v;
|
|
|
|
|
|
|
|
/* I'm not sure this works so well. */
|
|
|
|
#if G_SIZEOF_LONG > 4
|
|
|
|
return (guint) (val ^ (val >> 32));
|
|
|
|
#else
|
|
|
|
return val;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2001-06-10 03:17:15 +00:00
|
|
|
static int
|
2001-08-07 05:52:51 +00:00
|
|
|
set_utf8_string_hint (MetaDisplay *display,
|
|
|
|
Window xwindow,
|
|
|
|
Atom atom,
|
|
|
|
const char *val)
|
2001-06-10 03:17:15 +00:00
|
|
|
{
|
|
|
|
meta_error_trap_push (display);
|
|
|
|
XChangeProperty (display->xdisplay,
|
|
|
|
xwindow, atom,
|
2001-08-07 05:52:51 +00:00
|
|
|
display->atom_utf8_string,
|
2001-06-10 03:17:15 +00:00
|
|
|
8, PropModeReplace, (guchar*) val, strlen (val) + 1);
|
|
|
|
return meta_error_trap_pop (display);
|
|
|
|
}
|
2001-05-30 15:36:31 +00:00
|
|
|
|
|
|
|
gboolean
|
|
|
|
meta_display_open (const char *name)
|
|
|
|
{
|
|
|
|
MetaDisplay *display;
|
|
|
|
Display *xdisplay;
|
2001-05-31 03:30:58 +00:00
|
|
|
GSList *screens;
|
2001-05-31 06:42:58 +00:00
|
|
|
GSList *tmp;
|
2001-06-04 06:17:52 +00:00
|
|
|
/* Remember to edit code that assigns each atom to display struct
|
|
|
|
* when adding an atom name here.
|
|
|
|
*/
|
|
|
|
char *atom_names[] = {
|
|
|
|
"_NET_WM_NAME",
|
|
|
|
"WM_PROTOCOLS",
|
|
|
|
"WM_TAKE_FOCUS",
|
2001-06-06 04:47:37 +00:00
|
|
|
"WM_DELETE_WINDOW",
|
2001-06-07 05:18:10 +00:00
|
|
|
"WM_STATE",
|
2001-06-08 06:39:38 +00:00
|
|
|
"_NET_CLOSE_WINDOW",
|
|
|
|
"_NET_WM_STATE",
|
2001-06-21 06:08:35 +00:00
|
|
|
"_MOTIF_WM_HINTS",
|
2001-06-08 06:39:38 +00:00
|
|
|
"_NET_WM_STATE_SHADED",
|
|
|
|
"_NET_WM_STATE_MAXIMIZED_HORZ",
|
2001-06-09 05:14:43 +00:00
|
|
|
"_NET_WM_STATE_MAXIMIZED_VERT",
|
|
|
|
"_NET_WM_DESKTOP",
|
2001-06-09 21:58:30 +00:00
|
|
|
"_NET_NUMBER_OF_DESKTOPS",
|
|
|
|
"WM_CHANGE_STATE",
|
|
|
|
"SM_CLIENT_ID",
|
|
|
|
"WM_CLIENT_LEADER",
|
2001-06-10 03:17:15 +00:00
|
|
|
"WM_WINDOW_ROLE",
|
|
|
|
"_NET_CURRENT_DESKTOP",
|
|
|
|
"_NET_SUPPORTING_WM_CHECK",
|
2001-08-29 04:16:30 +00:00
|
|
|
"_NET_SUPPORTED",
|
2001-06-10 03:17:15 +00:00
|
|
|
"_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",
|
2001-06-10 07:52:35 +00:00
|
|
|
"_NET_WM_STATE_MODAL",
|
|
|
|
"_NET_CLIENT_LIST",
|
2001-06-11 05:16:24 +00:00
|
|
|
"_NET_CLIENT_LIST_STACKING",
|
|
|
|
"_NET_WM_STATE_SKIP_TASKBAR",
|
2001-06-13 00:56:08 +00:00
|
|
|
"_NET_WM_STATE_SKIP_PAGER",
|
2001-06-21 06:08:35 +00:00
|
|
|
"_WIN_WORKSPACE",
|
2001-06-23 05:49:35 +00:00
|
|
|
"_WIN_LAYER",
|
|
|
|
"_WIN_PROTOCOLS",
|
2001-06-24 03:18:10 +00:00
|
|
|
"_WIN_SUPPORTING_WM_CHECK",
|
|
|
|
"_NET_WM_ICON_NAME",
|
2001-08-05 16:04:52 +00:00
|
|
|
"_NET_WM_ICON",
|
2001-08-07 05:52:51 +00:00
|
|
|
"_NET_WM_ICON_GEOMETRY",
|
2001-08-20 01:42:44 +00:00
|
|
|
"UTF8_STRING",
|
2001-08-22 06:01:01 +00:00
|
|
|
"WM_ICON_SIZE",
|
2001-08-29 04:16:30 +00:00
|
|
|
"_KWM_WIN_ICON",
|
2001-10-07 23:06:19 +00:00
|
|
|
"_NET_WM_MOVERESIZE",
|
2001-10-15 04:14:58 +00:00
|
|
|
"_NET_ACTIVE_WINDOW",
|
|
|
|
"_METACITY_RESTART_MESSAGE"
|
2001-06-04 06:17:52 +00:00
|
|
|
};
|
2001-06-02 04:14:18 +00:00
|
|
|
Atom atoms[G_N_ELEMENTS(atom_names)];
|
|
|
|
|
2001-05-30 15:36:31 +00:00
|
|
|
meta_verbose ("Opening display '%s'\n", XDisplayName (name));
|
|
|
|
|
2001-06-20 03:01:26 +00:00
|
|
|
#ifdef USE_GDK_DISPLAY
|
|
|
|
xdisplay = meta_ui_get_display (name);
|
|
|
|
#else
|
|
|
|
xdisplay = XOpenDisplay (name);
|
|
|
|
#endif
|
|
|
|
|
2001-05-30 15:36:31 +00:00
|
|
|
if (xdisplay == NULL)
|
|
|
|
{
|
|
|
|
meta_warning (_("Failed to open X Window System display '%s'\n"),
|
|
|
|
XDisplayName (name));
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2001-05-31 06:42:58 +00:00
|
|
|
if (meta_is_syncing ())
|
|
|
|
XSynchronize (xdisplay, True);
|
|
|
|
|
2001-05-31 03:30:58 +00:00
|
|
|
display = g_new (MetaDisplay, 1);
|
2001-06-03 01:33:27 +00:00
|
|
|
|
|
|
|
/* here we use XDisplayName which is what the user
|
|
|
|
* probably put in, vs. DisplayString(display) which is
|
|
|
|
* canonicalized by XOpenDisplay()
|
|
|
|
*/
|
2001-05-30 15:36:31 +00:00
|
|
|
display->name = g_strdup (XDisplayName (name));
|
|
|
|
display->xdisplay = xdisplay;
|
2001-05-31 03:30:58 +00:00
|
|
|
display->error_traps = NULL;
|
2001-06-09 05:14:43 +00:00
|
|
|
display->server_grab_count = 0;
|
2001-06-06 04:47:37 +00:00
|
|
|
display->workspaces = NULL;
|
2001-06-24 03:41:44 +00:00
|
|
|
|
|
|
|
display->focus_window = NULL;
|
|
|
|
display->prev_focus_window = NULL;
|
2001-10-15 03:39:41 +00:00
|
|
|
|
|
|
|
display->showing_desktop = FALSE;
|
2001-06-06 04:47:37 +00:00
|
|
|
|
2001-05-31 03:30:58 +00:00
|
|
|
/* we have to go ahead and do this so error handlers work */
|
2001-05-30 15:36:31 +00:00
|
|
|
all_displays = g_slist_prepend (all_displays, display);
|
2001-06-06 04:47:37 +00:00
|
|
|
|
|
|
|
meta_display_init_keys (display);
|
2001-06-09 05:14:43 +00:00
|
|
|
|
|
|
|
XInternAtoms (display->xdisplay, atom_names, G_N_ELEMENTS (atom_names),
|
|
|
|
False, atoms);
|
|
|
|
display->atom_net_wm_name = atoms[0];
|
|
|
|
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];
|
|
|
|
display->atom_net_close_window = atoms[5];
|
|
|
|
display->atom_net_wm_state = atoms[6];
|
|
|
|
display->atom_motif_wm_hints = atoms[7];
|
|
|
|
display->atom_net_wm_state_shaded = atoms[8];
|
|
|
|
display->atom_net_wm_state_maximized_horz = atoms[9];
|
|
|
|
display->atom_net_wm_state_maximized_vert = atoms[10];
|
|
|
|
display->atom_net_wm_desktop = atoms[11];
|
|
|
|
display->atom_net_number_of_desktops = atoms[12];
|
2001-06-09 21:58:30 +00:00
|
|
|
display->atom_wm_change_state = atoms[13];
|
|
|
|
display->atom_sm_client_id = atoms[14];
|
|
|
|
display->atom_wm_client_leader = atoms[15];
|
|
|
|
display->atom_wm_window_role = atoms[16];
|
2001-06-10 03:17:15 +00:00
|
|
|
display->atom_net_current_desktop = atoms[17];
|
|
|
|
display->atom_net_supporting_wm_check = atoms[18];
|
2001-08-29 04:16:30 +00:00
|
|
|
display->atom_net_supported = atoms[19];
|
2001-06-10 03:17:15 +00:00
|
|
|
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];
|
2001-06-10 07:52:35 +00:00
|
|
|
display->atom_net_client_list = atoms[28];
|
|
|
|
display->atom_net_client_list_stacking = atoms[29];
|
2001-06-11 05:16:24 +00:00
|
|
|
display->atom_net_wm_state_skip_taskbar = atoms[30];
|
|
|
|
display->atom_net_wm_state_skip_pager = atoms[31];
|
2001-06-13 00:56:08 +00:00
|
|
|
display->atom_win_workspace = atoms[32];
|
2001-06-21 06:08:35 +00:00
|
|
|
display->atom_win_layer = atoms[33];
|
2001-06-23 05:49:35 +00:00
|
|
|
display->atom_win_protocols = atoms[34];
|
|
|
|
display->atom_win_supporting_wm_check = atoms[35];
|
2001-06-24 03:18:10 +00:00
|
|
|
display->atom_net_wm_icon_name = atoms[36];
|
|
|
|
display->atom_net_wm_icon = atoms[37];
|
2001-08-05 16:04:52 +00:00
|
|
|
display->atom_net_wm_icon_geometry = atoms[38];
|
2001-08-07 05:52:51 +00:00
|
|
|
display->atom_utf8_string = atoms[39];
|
2001-08-20 01:42:44 +00:00
|
|
|
display->atom_wm_icon_size = atoms[40];
|
2001-08-22 06:01:01 +00:00
|
|
|
display->atom_kwm_win_icon = atoms[41];
|
2001-08-29 04:16:30 +00:00
|
|
|
display->atom_net_wm_moveresize = atoms[42];
|
2001-10-07 23:06:19 +00:00
|
|
|
display->atom_net_active_window = atoms[43];
|
2001-10-15 04:14:58 +00:00
|
|
|
display->atom_metacity_restart_message = atoms[44];
|
2001-06-13 00:56:08 +00:00
|
|
|
|
2001-06-10 19:23:28 +00:00
|
|
|
/* Offscreen unmapped window used for _NET_SUPPORTING_WM_CHECK,
|
|
|
|
* created in screen_new
|
|
|
|
*/
|
|
|
|
display->leader_window = None;
|
2001-06-17 19:53:45 +00:00
|
|
|
|
2001-06-18 06:11:53 +00:00
|
|
|
screens = NULL;
|
2001-06-17 19:53:45 +00:00
|
|
|
#if 0
|
|
|
|
/* disable multihead pending GTK support */
|
2001-05-30 15:36:31 +00:00
|
|
|
i = 0;
|
|
|
|
while (i < ScreenCount (xdisplay))
|
|
|
|
{
|
2001-05-31 03:30:58 +00:00
|
|
|
MetaScreen *screen;
|
|
|
|
|
|
|
|
screen = meta_screen_new (display, i);
|
|
|
|
|
|
|
|
if (screen)
|
|
|
|
screens = g_slist_prepend (screens, screen);
|
2001-05-30 15:36:31 +00:00
|
|
|
++i;
|
|
|
|
}
|
2001-06-17 19:53:45 +00:00
|
|
|
#else
|
2001-06-18 06:11:53 +00:00
|
|
|
{
|
|
|
|
MetaScreen *screen;
|
|
|
|
screen = meta_screen_new (display, DefaultScreen (xdisplay));
|
|
|
|
if (screen)
|
|
|
|
screens = g_slist_prepend (screens, screen);
|
|
|
|
}
|
2001-06-17 19:53:45 +00:00
|
|
|
#endif
|
2001-05-31 03:30:58 +00:00
|
|
|
|
|
|
|
if (screens == NULL)
|
|
|
|
{
|
|
|
|
/* This would typically happen because all the screens already
|
|
|
|
* have window managers
|
|
|
|
*/
|
2001-06-20 03:01:26 +00:00
|
|
|
#ifndef USE_GDK_DISPLAY
|
2001-05-31 03:30:58 +00:00
|
|
|
XCloseDisplay (xdisplay);
|
2001-06-20 03:01:26 +00:00
|
|
|
#endif
|
2001-05-31 03:30:58 +00:00
|
|
|
all_displays = g_slist_remove (all_displays, display);
|
|
|
|
g_free (display->name);
|
|
|
|
g_free (display);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
display->screens = screens;
|
2001-06-20 03:01:26 +00:00
|
|
|
|
|
|
|
#ifdef USE_GDK_DISPLAY
|
|
|
|
display->events = NULL;
|
|
|
|
|
|
|
|
/* Get events */
|
|
|
|
meta_ui_add_event_func (display->xdisplay,
|
|
|
|
event_callback,
|
|
|
|
display);
|
|
|
|
#else
|
2001-05-31 03:30:58 +00:00
|
|
|
display->events = meta_event_queue_new (display->xdisplay,
|
|
|
|
event_queue_callback,
|
|
|
|
display);
|
2001-06-20 03:01:26 +00:00
|
|
|
#endif
|
|
|
|
|
2001-05-31 03:30:58 +00:00
|
|
|
display->window_ids = g_hash_table_new (unsigned_long_hash, unsigned_long_equal);
|
2001-06-08 06:39:38 +00:00
|
|
|
|
2001-06-08 02:17:48 +00:00
|
|
|
display->double_click_time = 250;
|
|
|
|
display->last_button_time = 0;
|
|
|
|
display->last_button_xwindow = None;
|
|
|
|
display->last_button_num = 0;
|
|
|
|
display->is_double_click = FALSE;
|
2001-06-09 21:58:30 +00:00
|
|
|
|
2001-08-30 04:01:38 +00:00
|
|
|
display->last_ignored_unmap_serial = 0;
|
|
|
|
|
2001-07-11 06:22:00 +00:00
|
|
|
display->grab_op = META_GRAB_OP_NONE;
|
|
|
|
display->grab_window = NULL;
|
|
|
|
|
2001-08-07 05:52:51 +00:00
|
|
|
set_utf8_string_hint (display,
|
|
|
|
display->leader_window,
|
|
|
|
display->atom_net_wm_name,
|
|
|
|
"Metacity");
|
2001-06-23 06:54:28 +00:00
|
|
|
|
|
|
|
{
|
|
|
|
/* The legacy GNOME hint is to set a cardinal which is the window
|
|
|
|
* id of the supporting_wm_check window on the supporting_wm_check
|
|
|
|
* window itself
|
|
|
|
*/
|
|
|
|
gulong data[1];
|
|
|
|
|
|
|
|
data[0] = display->leader_window;
|
|
|
|
XChangeProperty (display->xdisplay,
|
|
|
|
display->leader_window,
|
|
|
|
display->atom_win_supporting_wm_check,
|
|
|
|
XA_CARDINAL,
|
|
|
|
32, PropModeReplace, (guchar*) data, 1);
|
|
|
|
}
|
2001-06-02 04:14:18 +00:00
|
|
|
|
2001-05-31 06:42:58 +00:00
|
|
|
/* Now manage all existing windows */
|
|
|
|
tmp = display->screens;
|
|
|
|
while (tmp != NULL)
|
|
|
|
{
|
|
|
|
meta_screen_manage_all_windows (tmp->data);
|
|
|
|
tmp = tmp->next;
|
|
|
|
}
|
2001-05-30 15:36:31 +00:00
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2001-06-03 18:33:59 +00:00
|
|
|
listify_func (gpointer key, gpointer value, gpointer data)
|
2001-05-30 15:36:31 +00:00
|
|
|
{
|
2001-06-03 18:33:59 +00:00
|
|
|
GSList **listp;
|
2001-05-30 15:36:31 +00:00
|
|
|
|
2001-06-03 18:33:59 +00:00
|
|
|
listp = data;
|
|
|
|
*listp = g_slist_prepend (*listp, value);
|
|
|
|
}
|
2001-05-30 15:36:31 +00:00
|
|
|
|
2001-06-03 18:33:59 +00:00
|
|
|
static gint
|
|
|
|
ptrcmp (gconstpointer a, gconstpointer b)
|
|
|
|
{
|
|
|
|
if (a < b)
|
|
|
|
return -1;
|
|
|
|
else if (a > b)
|
|
|
|
return 1;
|
|
|
|
else
|
|
|
|
return 0;
|
2001-05-30 15:36:31 +00:00
|
|
|
}
|
|
|
|
|
2001-06-24 08:09:10 +00:00
|
|
|
GSList*
|
|
|
|
meta_display_list_windows (MetaDisplay *display)
|
2001-05-30 15:36:31 +00:00
|
|
|
{
|
2001-06-03 18:33:59 +00:00
|
|
|
GSList *winlist;
|
|
|
|
GSList *tmp;
|
2001-06-24 08:09:10 +00:00
|
|
|
GSList *prev;
|
2001-06-03 18:33:59 +00:00
|
|
|
|
|
|
|
winlist = NULL;
|
2001-05-30 15:36:31 +00:00
|
|
|
g_hash_table_foreach (display->window_ids,
|
2001-06-03 18:33:59 +00:00
|
|
|
listify_func,
|
|
|
|
&winlist);
|
|
|
|
|
2001-06-24 08:09:10 +00:00
|
|
|
/* Uniquify the list, since both frame windows and plain
|
|
|
|
* windows are in the hash
|
|
|
|
*/
|
2001-06-03 18:33:59 +00:00
|
|
|
winlist = g_slist_sort (winlist, ptrcmp);
|
|
|
|
|
2001-06-24 08:09:10 +00:00
|
|
|
prev = NULL;
|
|
|
|
tmp = winlist;
|
|
|
|
while (tmp != NULL)
|
|
|
|
{
|
|
|
|
GSList *next;
|
|
|
|
|
|
|
|
next = tmp->next;
|
|
|
|
|
|
|
|
if (next &&
|
|
|
|
next->data == tmp->data)
|
|
|
|
{
|
|
|
|
/* Delete tmp from list */
|
|
|
|
|
|
|
|
if (prev)
|
|
|
|
prev->next = next;
|
|
|
|
|
|
|
|
if (tmp == winlist)
|
|
|
|
winlist = next;
|
|
|
|
|
|
|
|
g_slist_free_1 (tmp);
|
|
|
|
|
|
|
|
/* leave prev unchanged */
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
prev = tmp;
|
|
|
|
}
|
|
|
|
|
|
|
|
tmp = next;
|
|
|
|
}
|
|
|
|
|
|
|
|
return winlist;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
meta_display_close (MetaDisplay *display)
|
|
|
|
{
|
|
|
|
GSList *winlist;
|
|
|
|
GSList *tmp;
|
|
|
|
|
|
|
|
if (display->error_traps)
|
|
|
|
meta_bug ("Display closed with error traps pending\n");
|
|
|
|
|
|
|
|
winlist = meta_display_list_windows (display);
|
|
|
|
|
2001-06-04 06:17:52 +00:00
|
|
|
/* Unmanage all windows */
|
|
|
|
meta_display_grab (display);
|
2001-06-03 18:33:59 +00:00
|
|
|
tmp = winlist;
|
|
|
|
while (tmp != NULL)
|
2001-06-04 04:58:22 +00:00
|
|
|
{
|
2001-06-24 08:09:10 +00:00
|
|
|
meta_window_free (tmp->data);
|
2001-06-03 18:33:59 +00:00
|
|
|
|
2001-06-04 04:58:22 +00:00
|
|
|
tmp = tmp->next;
|
2001-06-03 18:33:59 +00:00
|
|
|
}
|
|
|
|
g_slist_free (winlist);
|
2001-06-04 06:17:52 +00:00
|
|
|
meta_display_ungrab (display);
|
2001-06-04 04:58:22 +00:00
|
|
|
|
2001-06-20 03:01:26 +00:00
|
|
|
#ifdef USE_GDK_DISPLAY
|
|
|
|
/* Stop caring about events */
|
|
|
|
meta_ui_remove_event_func (display->xdisplay,
|
|
|
|
event_callback,
|
|
|
|
display);
|
|
|
|
#endif
|
|
|
|
|
2001-06-04 04:58:22 +00:00
|
|
|
/* Must be after all calls to meta_window_free() since they
|
|
|
|
* unregister windows
|
|
|
|
*/
|
|
|
|
g_hash_table_destroy (display->window_ids);
|
2001-06-09 21:58:30 +00:00
|
|
|
|
2001-06-10 19:23:28 +00:00
|
|
|
if (display->leader_window != None)
|
|
|
|
XDestroyWindow (display->xdisplay, display->leader_window);
|
2001-06-20 03:01:26 +00:00
|
|
|
|
|
|
|
#ifndef USE_GDK_DISPLAY
|
2001-05-30 15:36:31 +00:00
|
|
|
meta_event_queue_free (display->events);
|
|
|
|
XCloseDisplay (display->xdisplay);
|
2001-06-20 03:01:26 +00:00
|
|
|
#endif
|
2001-05-30 15:36:31 +00:00
|
|
|
g_free (display->name);
|
|
|
|
|
|
|
|
all_displays = g_slist_remove (all_displays, display);
|
2001-10-15 04:14:58 +00:00
|
|
|
|
2001-05-30 15:36:31 +00:00
|
|
|
g_free (display);
|
|
|
|
|
|
|
|
if (all_displays == NULL)
|
|
|
|
{
|
2001-05-31 03:30:58 +00:00
|
|
|
meta_verbose ("Last display closed, exiting\n");
|
2001-05-30 15:36:31 +00:00
|
|
|
meta_quit (META_EXIT_SUCCESS);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
MetaScreen*
|
|
|
|
meta_display_screen_for_root (MetaDisplay *display,
|
|
|
|
Window xroot)
|
|
|
|
{
|
|
|
|
GSList *tmp;
|
|
|
|
|
|
|
|
tmp = display->screens;
|
|
|
|
while (tmp != NULL)
|
|
|
|
{
|
|
|
|
MetaScreen *screen = tmp->data;
|
|
|
|
|
|
|
|
if (xroot == screen->xroot)
|
|
|
|
return screen;
|
|
|
|
|
|
|
|
tmp = tmp->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2001-06-01 03:00:01 +00:00
|
|
|
MetaScreen*
|
|
|
|
meta_display_screen_for_x_screen (MetaDisplay *display,
|
|
|
|
Screen *xscreen)
|
|
|
|
{
|
|
|
|
GSList *tmp;
|
|
|
|
|
|
|
|
tmp = display->screens;
|
|
|
|
while (tmp != NULL)
|
|
|
|
{
|
|
|
|
MetaScreen *screen = tmp->data;
|
|
|
|
|
|
|
|
if (xscreen == screen->xscreen)
|
|
|
|
return screen;
|
|
|
|
|
|
|
|
tmp = tmp->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2001-05-31 06:42:58 +00:00
|
|
|
/* Grab/ungrab routines taken from fvwm */
|
|
|
|
void
|
|
|
|
meta_display_grab (MetaDisplay *display)
|
|
|
|
{
|
|
|
|
if (display->server_grab_count == 0)
|
|
|
|
{
|
|
|
|
XSync (display->xdisplay, False);
|
|
|
|
XGrabServer (display->xdisplay);
|
|
|
|
}
|
|
|
|
XSync (display->xdisplay, False);
|
|
|
|
display->server_grab_count += 1;
|
2001-06-11 03:24:20 +00:00
|
|
|
meta_verbose ("Grabbing display, grab count now %d\n",
|
|
|
|
display->server_grab_count);
|
2001-05-31 06:42:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
meta_display_ungrab (MetaDisplay *display)
|
|
|
|
{
|
|
|
|
if (display->server_grab_count == 0)
|
|
|
|
meta_bug ("Ungrabbed non-grabbed server\n");
|
2001-06-06 04:47:37 +00:00
|
|
|
|
2001-05-31 06:42:58 +00:00
|
|
|
display->server_grab_count -= 1;
|
|
|
|
if (display->server_grab_count == 0)
|
|
|
|
{
|
2001-06-06 04:47:37 +00:00
|
|
|
/* FIXME we want to purge all pending "queued" stuff
|
|
|
|
* at this point, such as window hide/show
|
|
|
|
*/
|
2001-06-11 03:24:20 +00:00
|
|
|
XSync (display->xdisplay, False);
|
2001-05-31 06:42:58 +00:00
|
|
|
XUngrabServer (display->xdisplay);
|
|
|
|
}
|
|
|
|
XSync (display->xdisplay, False);
|
2001-06-11 03:24:20 +00:00
|
|
|
|
|
|
|
meta_verbose ("Ungrabbing display, grab count now %d\n",
|
|
|
|
display->server_grab_count);
|
2001-05-31 06:42:58 +00:00
|
|
|
}
|
|
|
|
|
2001-05-31 03:30:58 +00:00
|
|
|
MetaDisplay*
|
|
|
|
meta_display_for_x_display (Display *xdisplay)
|
|
|
|
{
|
|
|
|
GSList *tmp;
|
|
|
|
|
|
|
|
tmp = all_displays;
|
|
|
|
while (tmp != NULL)
|
|
|
|
{
|
|
|
|
MetaDisplay *display = tmp->data;
|
|
|
|
|
|
|
|
if (display->xdisplay == xdisplay)
|
|
|
|
return display;
|
|
|
|
|
|
|
|
tmp = tmp->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2001-05-31 06:42:58 +00:00
|
|
|
GSList*
|
|
|
|
meta_displays_list (void)
|
|
|
|
{
|
|
|
|
return all_displays;
|
|
|
|
}
|
|
|
|
|
2001-06-08 02:17:48 +00:00
|
|
|
gboolean
|
|
|
|
meta_display_is_double_click (MetaDisplay *display)
|
|
|
|
{
|
|
|
|
return display->is_double_click;
|
|
|
|
}
|
|
|
|
|
2001-05-30 15:36:31 +00:00
|
|
|
static gboolean dump_events = TRUE;
|
|
|
|
|
2001-06-20 03:01:26 +00:00
|
|
|
|
2001-05-30 15:36:31 +00:00
|
|
|
static void
|
2001-06-20 03:01:26 +00:00
|
|
|
event_queue_callback (XEvent *event,
|
2001-05-30 15:36:31 +00:00
|
|
|
gpointer data)
|
2001-06-20 03:01:26 +00:00
|
|
|
{
|
|
|
|
event_callback (event, data);
|
|
|
|
}
|
|
|
|
|
2001-07-26 03:14:45 +00:00
|
|
|
static gboolean
|
|
|
|
grab_op_is_mouse (MetaGrabOp op)
|
|
|
|
{
|
|
|
|
switch (op)
|
|
|
|
{
|
|
|
|
case META_GRAB_OP_MOVING:
|
|
|
|
case META_GRAB_OP_RESIZING_SE:
|
|
|
|
case META_GRAB_OP_RESIZING_S:
|
|
|
|
case META_GRAB_OP_RESIZING_SW:
|
|
|
|
case META_GRAB_OP_RESIZING_N:
|
|
|
|
case META_GRAB_OP_RESIZING_NE:
|
|
|
|
case META_GRAB_OP_RESIZING_NW:
|
|
|
|
case META_GRAB_OP_RESIZING_W:
|
|
|
|
case META_GRAB_OP_RESIZING_E:
|
|
|
|
return TRUE;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
grab_op_is_keyboard (MetaGrabOp op)
|
|
|
|
{
|
|
|
|
switch (op)
|
|
|
|
{
|
|
|
|
case META_GRAB_OP_KEYBOARD_MOVING:
|
|
|
|
case META_GRAB_OP_KEYBOARD_RESIZING_UNKNOWN:
|
|
|
|
case META_GRAB_OP_KEYBOARD_RESIZING_S:
|
|
|
|
case META_GRAB_OP_KEYBOARD_RESIZING_N:
|
|
|
|
case META_GRAB_OP_KEYBOARD_RESIZING_W:
|
|
|
|
case META_GRAB_OP_KEYBOARD_RESIZING_E:
|
2001-08-19 18:09:10 +00:00
|
|
|
case META_GRAB_OP_KEYBOARD_RESIZING_SE:
|
|
|
|
case META_GRAB_OP_KEYBOARD_RESIZING_NE:
|
|
|
|
case META_GRAB_OP_KEYBOARD_RESIZING_SW:
|
|
|
|
case META_GRAB_OP_KEYBOARD_RESIZING_NW:
|
|
|
|
case META_GRAB_OP_KEYBOARD_TABBING:
|
2001-07-26 03:14:45 +00:00
|
|
|
return TRUE;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-06-20 03:01:26 +00:00
|
|
|
static gboolean
|
|
|
|
event_callback (XEvent *event,
|
|
|
|
gpointer data)
|
2001-05-30 15:36:31 +00:00
|
|
|
{
|
|
|
|
MetaWindow *window;
|
|
|
|
MetaDisplay *display;
|
2001-06-03 01:33:27 +00:00
|
|
|
Window modified;
|
2001-07-11 06:22:00 +00:00
|
|
|
gboolean frame_was_receiver;
|
2001-05-31 06:42:58 +00:00
|
|
|
|
2001-05-30 15:36:31 +00:00
|
|
|
display = data;
|
|
|
|
|
|
|
|
if (dump_events)
|
|
|
|
meta_spew_event (display, event);
|
2001-06-20 03:01:26 +00:00
|
|
|
|
2001-06-08 02:17:48 +00:00
|
|
|
/* mark double click events, kind of a hack, oh well. */
|
|
|
|
if (event->type == ButtonPress)
|
|
|
|
{
|
|
|
|
if (event->xbutton.button == display->last_button_num &&
|
|
|
|
event->xbutton.window == display->last_button_xwindow &&
|
|
|
|
event->xbutton.time < (display->last_button_time + display->double_click_time))
|
|
|
|
{
|
|
|
|
display->is_double_click = TRUE;
|
|
|
|
meta_verbose ("This was the second click of a double click\n");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
display->is_double_click = FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
display->last_button_num = event->xbutton.button;
|
|
|
|
display->last_button_xwindow = event->xbutton.window;
|
|
|
|
display->last_button_time = event->xbutton.time;
|
|
|
|
}
|
2001-08-30 04:01:38 +00:00
|
|
|
else if (event->type == UnmapNotify)
|
|
|
|
{
|
|
|
|
if (meta_ui_window_should_not_cause_focus (display->xdisplay,
|
|
|
|
event->xunmap.window))
|
|
|
|
{
|
|
|
|
display->last_ignored_unmap_serial = event->xany.serial;
|
|
|
|
meta_verbose ("Will not focus on EnterNotify with serial %lu\n",
|
|
|
|
display->last_ignored_unmap_serial);
|
|
|
|
}
|
|
|
|
}
|
2001-06-08 02:17:48 +00:00
|
|
|
|
2001-06-03 01:33:27 +00:00
|
|
|
modified = event_get_modified_window (display, event);
|
|
|
|
|
|
|
|
if (modified != None)
|
|
|
|
window = meta_display_lookup_x_window (display, modified);
|
|
|
|
else
|
|
|
|
window = NULL;
|
2001-07-11 06:22:00 +00:00
|
|
|
|
|
|
|
frame_was_receiver = FALSE;
|
2001-06-03 01:33:27 +00:00
|
|
|
if (window &&
|
|
|
|
window->frame &&
|
|
|
|
modified == window->frame->xwindow)
|
2001-07-11 06:22:00 +00:00
|
|
|
frame_was_receiver = TRUE;
|
2001-05-30 15:36:31 +00:00
|
|
|
|
|
|
|
switch (event->type)
|
|
|
|
{
|
|
|
|
case KeyPress:
|
|
|
|
case KeyRelease:
|
2001-07-26 03:58:24 +00:00
|
|
|
meta_display_process_key_event (display, window, event);
|
2001-05-30 15:36:31 +00:00
|
|
|
break;
|
|
|
|
case ButtonPress:
|
2001-07-26 03:14:45 +00:00
|
|
|
if ((grab_op_is_mouse (display->grab_op) &&
|
|
|
|
display->grab_button != event->xbutton.button &&
|
|
|
|
display->grab_window == window) ||
|
|
|
|
grab_op_is_keyboard (display->grab_op))
|
2001-07-11 06:22:00 +00:00
|
|
|
{
|
|
|
|
meta_verbose ("Ending grab op %d on window %s due to button press\n",
|
|
|
|
display->grab_op,
|
|
|
|
display->grab_window->desc);
|
|
|
|
meta_display_end_grab_op (display,
|
|
|
|
event->xbutton.time);
|
2001-08-19 18:09:10 +00:00
|
|
|
}
|
2001-07-26 03:58:24 +00:00
|
|
|
else if (window && display->grab_op == META_GRAB_OP_NONE)
|
2001-07-26 03:14:45 +00:00
|
|
|
{
|
2001-07-26 03:58:24 +00:00
|
|
|
gboolean begin_move = FALSE;
|
2001-10-14 04:11:42 +00:00
|
|
|
guint grab_mask;
|
|
|
|
|
|
|
|
grab_mask = Mod1Mask;
|
|
|
|
if (g_getenv ("METACITY_DEBUG_BUTTON_GRABS"))
|
|
|
|
grab_mask |= ControlMask;
|
2001-07-26 03:58:24 +00:00
|
|
|
|
2001-10-14 04:11:42 +00:00
|
|
|
if ((event->xbutton.state & grab_mask) == 0)
|
|
|
|
{
|
|
|
|
; /* nothing, not getting event from our button grabs,
|
|
|
|
* rather from a client that just let button presses
|
|
|
|
* pass through to our frame
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
else if (event->xbutton.button == 1)
|
2001-07-26 03:14:45 +00:00
|
|
|
{
|
|
|
|
meta_window_raise (window);
|
|
|
|
meta_window_focus (window, event->xbutton.time);
|
2001-07-26 03:58:24 +00:00
|
|
|
|
2001-10-14 04:11:42 +00:00
|
|
|
begin_move = TRUE;
|
2001-07-26 03:14:45 +00:00
|
|
|
}
|
|
|
|
else if (event->xbutton.button == 2)
|
|
|
|
{
|
2001-07-26 03:58:24 +00:00
|
|
|
begin_move = TRUE;
|
2001-07-26 03:14:45 +00:00
|
|
|
}
|
|
|
|
else if (event->xbutton.button == 3)
|
|
|
|
{
|
|
|
|
meta_window_show_menu (window,
|
|
|
|
event->xbutton.x_root,
|
|
|
|
event->xbutton.y_root,
|
|
|
|
event->xbutton.button,
|
|
|
|
event->xbutton.time);
|
|
|
|
}
|
2001-07-26 03:58:24 +00:00
|
|
|
|
|
|
|
if (begin_move && window->has_move_func)
|
|
|
|
{
|
|
|
|
meta_display_begin_grab_op (display,
|
|
|
|
window,
|
|
|
|
META_GRAB_OP_MOVING,
|
|
|
|
TRUE,
|
|
|
|
event->xbutton.button,
|
|
|
|
0,
|
|
|
|
event->xbutton.time,
|
|
|
|
event->xbutton.x_root,
|
|
|
|
event->xbutton.y_root);
|
|
|
|
}
|
2001-07-11 06:22:00 +00:00
|
|
|
}
|
2001-05-30 15:36:31 +00:00
|
|
|
break;
|
|
|
|
case ButtonRelease:
|
2001-07-26 03:14:45 +00:00
|
|
|
if (grab_op_is_mouse (display->grab_op) &&
|
|
|
|
display->grab_window == window)
|
|
|
|
meta_window_handle_mouse_grab_op_event (window, event);
|
2001-05-30 15:36:31 +00:00
|
|
|
break;
|
|
|
|
case MotionNotify:
|
2001-07-26 03:14:45 +00:00
|
|
|
if (grab_op_is_mouse (display->grab_op) &&
|
|
|
|
display->grab_window == window)
|
|
|
|
meta_window_handle_mouse_grab_op_event (window, event);
|
2001-05-30 15:36:31 +00:00
|
|
|
break;
|
|
|
|
case EnterNotify:
|
2001-06-04 04:58:22 +00:00
|
|
|
/* do this even if window->has_focus to avoid races */
|
2001-08-30 04:01:38 +00:00
|
|
|
if (window && event->xany.serial != display->last_ignored_unmap_serial)
|
2001-09-16 21:50:27 +00:00
|
|
|
{
|
2001-12-10 00:38:21 +00:00
|
|
|
switch (meta_prefs_get_focus_mode ())
|
|
|
|
{
|
|
|
|
case META_FOCUS_MODE_SLOPPY:
|
|
|
|
case META_FOCUS_MODE_MOUSE:
|
|
|
|
meta_window_focus (window, event->xcrossing.time);
|
|
|
|
break;
|
|
|
|
case META_FOCUS_MODE_CLICK:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2001-09-16 21:50:27 +00:00
|
|
|
if (window->type == META_WINDOW_DOCK)
|
|
|
|
meta_window_raise (window);
|
|
|
|
}
|
2001-05-30 15:36:31 +00:00
|
|
|
break;
|
|
|
|
case LeaveNotify:
|
2001-09-16 21:50:27 +00:00
|
|
|
if (window)
|
|
|
|
{
|
2001-12-10 00:38:21 +00:00
|
|
|
switch (meta_prefs_get_focus_mode ())
|
|
|
|
{
|
|
|
|
case META_FOCUS_MODE_MOUSE:
|
|
|
|
/* This is kind of questionable; but we normally
|
|
|
|
* set focus to RevertToPointerRoot, so I guess
|
|
|
|
* leaving it on PointerRoot when nothing is focused
|
|
|
|
* is probably right. Anyway, unfocus the
|
|
|
|
* focused window.
|
|
|
|
*/
|
|
|
|
if (window->has_focus)
|
|
|
|
XSetInputFocus (display->xdisplay,
|
|
|
|
PointerRoot,
|
|
|
|
RevertToPointerRoot,
|
|
|
|
event->xcrossing.time);
|
|
|
|
break;
|
|
|
|
case META_FOCUS_MODE_SLOPPY:
|
|
|
|
case META_FOCUS_MODE_CLICK:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2001-09-16 21:50:27 +00:00
|
|
|
if (window->type == META_WINDOW_DOCK)
|
|
|
|
meta_window_lower (window);
|
|
|
|
}
|
2001-05-30 15:36:31 +00:00
|
|
|
break;
|
|
|
|
case FocusIn:
|
|
|
|
case FocusOut:
|
2001-06-04 04:58:22 +00:00
|
|
|
if (window)
|
2001-06-23 05:26:28 +00:00
|
|
|
meta_window_notify_focus (window, event);
|
2001-05-30 15:36:31 +00:00
|
|
|
break;
|
|
|
|
case KeymapNotify:
|
|
|
|
break;
|
|
|
|
case Expose:
|
|
|
|
break;
|
|
|
|
case GraphicsExpose:
|
|
|
|
break;
|
|
|
|
case NoExpose:
|
|
|
|
break;
|
|
|
|
case VisibilityNotify:
|
|
|
|
break;
|
|
|
|
case CreateNotify:
|
|
|
|
break;
|
|
|
|
case DestroyNotify:
|
2001-06-03 01:33:27 +00:00
|
|
|
if (window)
|
2001-07-11 06:22:00 +00:00
|
|
|
{
|
2001-07-26 03:14:45 +00:00
|
|
|
if (display->grab_op != META_GRAB_OP_NONE &&
|
|
|
|
display->grab_window == window)
|
|
|
|
meta_display_end_grab_op (display, CurrentTime);
|
|
|
|
|
2001-07-11 06:22:00 +00:00
|
|
|
if (frame_was_receiver)
|
|
|
|
{
|
|
|
|
meta_warning ("Unexpected destruction of frame 0x%lx, not sure if this should silently fail or be considered a bug\n",
|
|
|
|
window->frame->xwindow);
|
|
|
|
meta_error_trap_push (display);
|
|
|
|
meta_window_destroy_frame (window->frame->window);
|
|
|
|
meta_error_trap_pop (display);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
meta_window_free (window); /* Unmanage destroyed window */
|
|
|
|
}
|
|
|
|
}
|
2001-05-30 15:36:31 +00:00
|
|
|
break;
|
|
|
|
case UnmapNotify:
|
2001-07-26 03:14:45 +00:00
|
|
|
if (display->grab_op != META_GRAB_OP_NONE &&
|
|
|
|
display->grab_window == window)
|
|
|
|
meta_display_end_grab_op (display, CurrentTime);
|
|
|
|
|
|
|
|
/* Unfocus on UnmapNotify */
|
|
|
|
if (window)
|
|
|
|
meta_window_notify_focus (window, event);
|
|
|
|
|
2001-07-11 06:22:00 +00:00
|
|
|
if (!frame_was_receiver && window)
|
2001-06-04 06:17:52 +00:00
|
|
|
{
|
2001-06-11 03:24:20 +00:00
|
|
|
if (window->unmaps_pending == 0)
|
|
|
|
{
|
|
|
|
meta_verbose ("Window %s withdrawn\n",
|
|
|
|
window->desc);
|
2001-06-23 18:30:27 +00:00
|
|
|
window->withdrawn = TRUE;
|
2001-06-11 03:24:20 +00:00
|
|
|
meta_window_free (window); /* Unmanage withdrawn window */
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
window->unmaps_pending -= 1;
|
|
|
|
meta_verbose ("Received pending unmap, %d now pending\n",
|
|
|
|
window->unmaps_pending);
|
|
|
|
}
|
2001-06-04 06:17:52 +00:00
|
|
|
}
|
2001-05-30 15:36:31 +00:00
|
|
|
break;
|
|
|
|
case MapNotify:
|
|
|
|
break;
|
|
|
|
case MapRequest:
|
2001-06-03 01:33:27 +00:00
|
|
|
if (window == NULL)
|
2001-07-11 06:22:00 +00:00
|
|
|
{
|
|
|
|
window = meta_window_new (display, event->xmaprequest.window,
|
|
|
|
FALSE);
|
|
|
|
}
|
|
|
|
/* if frame was receiver it's some malicious send event or something */
|
|
|
|
else if (!frame_was_receiver && window)
|
2001-06-11 06:39:12 +00:00
|
|
|
{
|
|
|
|
if (window->minimized)
|
|
|
|
meta_window_unminimize (window);
|
|
|
|
}
|
2001-05-30 15:36:31 +00:00
|
|
|
break;
|
|
|
|
case ReparentNotify:
|
|
|
|
break;
|
|
|
|
case ConfigureNotify:
|
|
|
|
break;
|
|
|
|
case ConfigureRequest:
|
2001-06-03 01:33:27 +00:00
|
|
|
/* This comment and code is found in both twm and fvwm */
|
|
|
|
/*
|
|
|
|
* According to the July 27, 1988 ICCCM draft, we should ignore size and
|
|
|
|
* position fields in the WM_NORMAL_HINTS property when we map a window.
|
|
|
|
* Instead, we'll read the current geometry. Therefore, we should respond
|
|
|
|
* to configuration requests for windows which have never been mapped.
|
|
|
|
*/
|
|
|
|
if (window == NULL)
|
|
|
|
{
|
|
|
|
unsigned int xwcm;
|
|
|
|
XWindowChanges xwc;
|
|
|
|
|
|
|
|
xwcm = event->xconfigurerequest.value_mask &
|
|
|
|
(CWX | CWY | CWWidth | CWHeight | CWBorderWidth);
|
|
|
|
|
|
|
|
xwc.x = event->xconfigurerequest.x;
|
|
|
|
xwc.y = event->xconfigurerequest.y;
|
|
|
|
xwc.width = event->xconfigurerequest.width;
|
|
|
|
xwc.height = event->xconfigurerequest.height;
|
|
|
|
xwc.border_width = event->xconfigurerequest.border_width;
|
|
|
|
|
2001-06-11 05:47:51 +00:00
|
|
|
meta_verbose ("Configuring withdrawn window to %d,%d %dx%d border %d (some values may not be in mask)\n",
|
2001-06-08 06:39:38 +00:00
|
|
|
xwc.x, xwc.y, xwc.width, xwc.height, xwc.border_width);
|
2001-08-03 04:20:27 +00:00
|
|
|
meta_error_trap_push (display);
|
2001-06-03 01:33:27 +00:00
|
|
|
XConfigureWindow (display->xdisplay, event->xconfigurerequest.window,
|
|
|
|
xwcm, &xwc);
|
2001-08-03 04:20:27 +00:00
|
|
|
meta_error_trap_pop (display);
|
2001-06-03 01:33:27 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2001-07-11 06:22:00 +00:00
|
|
|
if (!frame_was_receiver)
|
|
|
|
meta_window_configure_request (window, event);
|
2001-06-03 01:33:27 +00:00
|
|
|
}
|
2001-05-30 15:36:31 +00:00
|
|
|
break;
|
|
|
|
case GravityNotify:
|
|
|
|
break;
|
|
|
|
case ResizeRequest:
|
|
|
|
break;
|
|
|
|
case CirculateNotify:
|
|
|
|
break;
|
|
|
|
case CirculateRequest:
|
|
|
|
break;
|
|
|
|
case PropertyNotify:
|
2001-07-11 06:22:00 +00:00
|
|
|
if (window && !frame_was_receiver)
|
2001-06-03 01:33:27 +00:00
|
|
|
meta_window_property_notify (window, event);
|
2001-05-30 15:36:31 +00:00
|
|
|
break;
|
|
|
|
case SelectionClear:
|
|
|
|
break;
|
|
|
|
case SelectionRequest:
|
|
|
|
break;
|
|
|
|
case SelectionNotify:
|
|
|
|
break;
|
|
|
|
case ColormapNotify:
|
|
|
|
break;
|
|
|
|
case ClientMessage:
|
2001-06-07 05:18:10 +00:00
|
|
|
if (window)
|
2001-06-10 03:17:15 +00:00
|
|
|
{
|
2001-07-11 06:22:00 +00:00
|
|
|
if (!frame_was_receiver)
|
|
|
|
meta_window_client_message (window, event);
|
2001-06-10 03:17:15 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
MetaScreen *screen;
|
|
|
|
|
|
|
|
screen = meta_display_screen_for_root (display,
|
|
|
|
event->xclient.window);
|
|
|
|
|
2001-10-07 23:06:19 +00:00
|
|
|
if (screen)
|
2001-06-10 03:17:15 +00:00
|
|
|
{
|
2001-10-15 04:14:58 +00:00
|
|
|
meta_debug_spew ("client for screen\n");
|
2001-10-07 23:06:19 +00:00
|
|
|
if (event->xclient.message_type ==
|
|
|
|
display->atom_net_current_desktop)
|
|
|
|
{
|
|
|
|
int space;
|
|
|
|
MetaWorkspace *workspace;
|
2001-06-10 03:17:15 +00:00
|
|
|
|
2001-10-07 23:06:19 +00:00
|
|
|
space = event->xclient.data.l[0];
|
2001-06-10 03:17:15 +00:00
|
|
|
|
2001-10-07 23:06:19 +00:00
|
|
|
meta_verbose ("Request to change current workspace to %d\n",
|
|
|
|
space);
|
2001-06-10 03:17:15 +00:00
|
|
|
|
2001-10-07 23:06:19 +00:00
|
|
|
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);
|
|
|
|
}
|
2001-10-15 04:14:58 +00:00
|
|
|
else if (event->xclient.message_type ==
|
|
|
|
display->atom_metacity_restart_message)
|
|
|
|
{
|
|
|
|
meta_verbose ("Received restart request\n");
|
|
|
|
meta_restart ();
|
|
|
|
}
|
2001-06-10 03:17:15 +00:00
|
|
|
}
|
|
|
|
}
|
2001-05-30 15:36:31 +00:00
|
|
|
break;
|
|
|
|
case MappingNotify:
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
2001-06-03 01:33:27 +00:00
|
|
|
}
|
2001-06-20 03:01:26 +00:00
|
|
|
|
|
|
|
return FALSE;
|
2001-05-30 15:36:31 +00:00
|
|
|
}
|
|
|
|
|
2001-06-03 01:33:27 +00:00
|
|
|
/* Return the window this has to do with, if any, rather
|
|
|
|
* than the frame or root window that was selecting
|
|
|
|
* for substructure
|
|
|
|
*/
|
|
|
|
static Window
|
|
|
|
event_get_modified_window (MetaDisplay *display,
|
|
|
|
XEvent *event)
|
|
|
|
{
|
|
|
|
switch (event->type)
|
|
|
|
{
|
|
|
|
case KeyPress:
|
|
|
|
case KeyRelease:
|
|
|
|
case ButtonPress:
|
|
|
|
case ButtonRelease:
|
|
|
|
case MotionNotify:
|
|
|
|
case FocusIn:
|
|
|
|
case FocusOut:
|
|
|
|
case KeymapNotify:
|
|
|
|
case Expose:
|
|
|
|
case GraphicsExpose:
|
|
|
|
case NoExpose:
|
|
|
|
case VisibilityNotify:
|
|
|
|
case ResizeRequest:
|
|
|
|
case PropertyNotify:
|
|
|
|
case SelectionClear:
|
|
|
|
case SelectionRequest:
|
|
|
|
case SelectionNotify:
|
|
|
|
case ColormapNotify:
|
|
|
|
case ClientMessage:
|
2001-06-04 04:58:22 +00:00
|
|
|
case EnterNotify:
|
|
|
|
case LeaveNotify:
|
2001-06-03 01:33:27 +00:00
|
|
|
return event->xany.window;
|
2001-06-04 04:58:22 +00:00
|
|
|
|
2001-06-03 01:33:27 +00:00
|
|
|
case CreateNotify:
|
|
|
|
return event->xcreatewindow.window;
|
|
|
|
|
|
|
|
case DestroyNotify:
|
|
|
|
return event->xdestroywindow.window;
|
|
|
|
|
|
|
|
case UnmapNotify:
|
|
|
|
return event->xunmap.window;
|
|
|
|
|
|
|
|
case MapNotify:
|
|
|
|
return event->xmap.window;
|
|
|
|
|
|
|
|
case MapRequest:
|
|
|
|
return event->xmaprequest.window;
|
|
|
|
|
|
|
|
case ReparentNotify:
|
|
|
|
return event->xreparent.window;
|
|
|
|
|
|
|
|
case ConfigureNotify:
|
|
|
|
return event->xconfigure.window;
|
|
|
|
|
|
|
|
case ConfigureRequest:
|
|
|
|
return event->xconfigurerequest.window;
|
|
|
|
|
|
|
|
case GravityNotify:
|
|
|
|
return event->xgravity.window;
|
|
|
|
|
|
|
|
case CirculateNotify:
|
|
|
|
return event->xcirculate.window;
|
|
|
|
|
|
|
|
case CirculateRequest:
|
|
|
|
return event->xcirculaterequest.window;
|
|
|
|
|
|
|
|
case MappingNotify:
|
|
|
|
return None;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return None;
|
|
|
|
}
|
|
|
|
}
|
2001-06-10 19:23:28 +00:00
|
|
|
|
|
|
|
static const char*
|
|
|
|
focus_detail (int d)
|
|
|
|
{
|
2001-06-18 06:11:53 +00:00
|
|
|
const char *detail = "???";
|
2001-06-10 19:23:28 +00:00
|
|
|
switch (d)
|
|
|
|
{
|
|
|
|
case NotifyAncestor:
|
|
|
|
detail = "NotifyAncestor";
|
|
|
|
break;
|
|
|
|
case NotifyDetailNone:
|
|
|
|
detail = "NotifyDetailNone";
|
|
|
|
break;
|
|
|
|
case NotifyInferior:
|
|
|
|
detail = "NotifyInferior";
|
|
|
|
break;
|
|
|
|
case NotifyNonlinear:
|
|
|
|
detail = "NotifyNonlinear";
|
|
|
|
break;
|
|
|
|
case NotifyNonlinearVirtual:
|
|
|
|
detail = "NotifyNonlinearVirtual";
|
|
|
|
break;
|
|
|
|
case NotifyPointer:
|
|
|
|
detail = "NotifyPointer";
|
|
|
|
break;
|
|
|
|
case NotifyPointerRoot:
|
|
|
|
detail = "NotifyPointerRoot";
|
|
|
|
break;
|
|
|
|
case NotifyVirtual:
|
|
|
|
detail = "NotifyVirtual";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return detail;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const char*
|
|
|
|
focus_mode (int m)
|
|
|
|
{
|
2001-06-18 06:11:53 +00:00
|
|
|
const char *mode = "???";
|
2001-06-10 19:23:28 +00:00
|
|
|
switch (m)
|
|
|
|
{
|
|
|
|
case NotifyNormal:
|
|
|
|
mode = "NotifyNormal";
|
|
|
|
break;
|
|
|
|
case NotifyGrab:
|
|
|
|
mode = "NotifyGrab";
|
|
|
|
break;
|
|
|
|
case NotifyUngrab:
|
|
|
|
mode = "NotifyUngrab";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return mode;
|
|
|
|
}
|
|
|
|
|
2001-07-26 03:58:24 +00:00
|
|
|
static char*
|
|
|
|
key_event_description (Display *xdisplay,
|
|
|
|
XEvent *event)
|
|
|
|
{
|
|
|
|
KeySym keysym;
|
|
|
|
|
|
|
|
keysym = XKeycodeToKeysym (xdisplay, event->xkey.keycode, 0);
|
|
|
|
|
|
|
|
return g_strdup_printf ("Key '%s' state 0x%x",
|
|
|
|
XKeysymToString (keysym), event->xkey.state);
|
|
|
|
}
|
|
|
|
|
2001-05-30 15:36:31 +00:00
|
|
|
static void
|
|
|
|
meta_spew_event (MetaDisplay *display,
|
|
|
|
XEvent *event)
|
|
|
|
{
|
|
|
|
const char *name = NULL;
|
|
|
|
char *extra = NULL;
|
|
|
|
char *winname;
|
|
|
|
MetaScreen *screen;
|
2001-06-10 18:46:46 +00:00
|
|
|
|
|
|
|
/* filter overnumerous events */
|
|
|
|
if (event->type == Expose || event->type == MotionNotify ||
|
|
|
|
event->type == NoExpose)
|
|
|
|
return;
|
2001-05-30 15:36:31 +00:00
|
|
|
|
|
|
|
switch (event->type)
|
|
|
|
{
|
|
|
|
case KeyPress:
|
2001-07-11 06:22:00 +00:00
|
|
|
name = "KeyPress";
|
2001-07-26 03:58:24 +00:00
|
|
|
extra = key_event_description (display->xdisplay, event);
|
2001-05-30 15:36:31 +00:00
|
|
|
break;
|
|
|
|
case KeyRelease:
|
|
|
|
name = "KeyRelease";
|
2001-07-26 03:58:24 +00:00
|
|
|
extra = key_event_description (display->xdisplay, event);
|
2001-05-30 15:36:31 +00:00
|
|
|
break;
|
|
|
|
case ButtonPress:
|
|
|
|
name = "ButtonPress";
|
|
|
|
break;
|
|
|
|
case ButtonRelease:
|
|
|
|
name = "ButtonRelease";
|
|
|
|
break;
|
|
|
|
case MotionNotify:
|
|
|
|
name = "MotionNotify";
|
|
|
|
break;
|
|
|
|
case EnterNotify:
|
|
|
|
name = "EnterNotify";
|
2001-06-11 03:24:20 +00:00
|
|
|
extra = g_strdup_printf ("win: 0x%lx root: 0x%lx subwindow: 0x%lx mode: %d detail: %d",
|
2001-06-04 04:58:22 +00:00
|
|
|
event->xcrossing.window,
|
|
|
|
event->xcrossing.root,
|
|
|
|
event->xcrossing.subwindow,
|
|
|
|
event->xcrossing.mode,
|
|
|
|
event->xcrossing.detail);
|
2001-05-30 15:36:31 +00:00
|
|
|
break;
|
|
|
|
case LeaveNotify:
|
|
|
|
name = "LeaveNotify";
|
2001-06-11 03:24:20 +00:00
|
|
|
extra = g_strdup_printf ("win: 0x%lx root: 0x%lx subwindow: 0x%lx mode: %d detail: %d",
|
2001-06-04 04:58:22 +00:00
|
|
|
event->xcrossing.window,
|
|
|
|
event->xcrossing.root,
|
|
|
|
event->xcrossing.subwindow,
|
|
|
|
event->xcrossing.mode,
|
|
|
|
event->xcrossing.detail);
|
2001-05-30 15:36:31 +00:00
|
|
|
break;
|
|
|
|
case FocusIn:
|
|
|
|
name = "FocusIn";
|
2001-06-10 19:23:28 +00:00
|
|
|
extra = g_strdup_printf ("detail: %s mode: %s\n",
|
|
|
|
focus_detail (event->xfocus.detail),
|
|
|
|
focus_mode (event->xfocus.mode));
|
2001-05-30 15:36:31 +00:00
|
|
|
break;
|
|
|
|
case FocusOut:
|
|
|
|
name = "FocusOut";
|
2001-06-10 19:23:28 +00:00
|
|
|
extra = g_strdup_printf ("detail: %s mode: %s\n",
|
|
|
|
focus_detail (event->xfocus.detail),
|
|
|
|
focus_mode (event->xfocus.mode));
|
2001-05-30 15:36:31 +00:00
|
|
|
break;
|
|
|
|
case KeymapNotify:
|
|
|
|
name = "KeymapNotify";
|
|
|
|
break;
|
|
|
|
case Expose:
|
|
|
|
name = "Expose";
|
|
|
|
break;
|
|
|
|
case GraphicsExpose:
|
|
|
|
name = "GraphicsExpose";
|
|
|
|
break;
|
|
|
|
case NoExpose:
|
|
|
|
name = "NoExpose";
|
|
|
|
break;
|
|
|
|
case VisibilityNotify:
|
|
|
|
name = "VisibilityNotify";
|
|
|
|
break;
|
|
|
|
case CreateNotify:
|
|
|
|
name = "CreateNotify";
|
|
|
|
break;
|
|
|
|
case DestroyNotify:
|
|
|
|
name = "DestroyNotify";
|
|
|
|
break;
|
|
|
|
case UnmapNotify:
|
|
|
|
name = "UnmapNotify";
|
|
|
|
break;
|
|
|
|
case MapNotify:
|
|
|
|
name = "MapNotify";
|
|
|
|
break;
|
|
|
|
case MapRequest:
|
|
|
|
name = "MapRequest";
|
|
|
|
break;
|
|
|
|
case ReparentNotify:
|
|
|
|
name = "ReparentNotify";
|
|
|
|
break;
|
|
|
|
case ConfigureNotify:
|
|
|
|
name = "ConfigureNotify";
|
|
|
|
extra = g_strdup_printf ("x: %d y: %d w: %d h: %d above: 0x%lx",
|
|
|
|
event->xconfigure.x,
|
|
|
|
event->xconfigure.y,
|
|
|
|
event->xconfigure.width,
|
|
|
|
event->xconfigure.height,
|
|
|
|
event->xconfigure.above);
|
|
|
|
break;
|
|
|
|
case ConfigureRequest:
|
|
|
|
name = "ConfigureRequest";
|
2001-06-11 05:47:51 +00:00
|
|
|
extra = g_strdup_printf ("parent: 0x%lx window: 0x%lx x: %d %sy: %d %sw: %d %sh: %d %sborder: %d %s",
|
2001-06-03 01:33:27 +00:00
|
|
|
event->xconfigurerequest.parent,
|
|
|
|
event->xconfigurerequest.window,
|
|
|
|
event->xconfigurerequest.x,
|
2001-06-11 05:47:51 +00:00
|
|
|
event->xconfigurerequest.value_mask &
|
|
|
|
CWX ? "" : "(unset) ",
|
2001-06-03 01:33:27 +00:00
|
|
|
event->xconfigurerequest.y,
|
2001-06-11 05:47:51 +00:00
|
|
|
event->xconfigurerequest.value_mask &
|
|
|
|
CWY ? "" : "(unset) ",
|
2001-06-03 01:33:27 +00:00
|
|
|
event->xconfigurerequest.width,
|
2001-06-11 05:47:51 +00:00
|
|
|
event->xconfigurerequest.value_mask &
|
|
|
|
CWWidth ? "" : "(unset) ",
|
2001-06-03 01:33:27 +00:00
|
|
|
event->xconfigurerequest.height,
|
2001-06-11 05:47:51 +00:00
|
|
|
event->xconfigurerequest.value_mask &
|
|
|
|
CWHeight ? "" : "(unset) ",
|
|
|
|
event->xconfigurerequest.border_width,
|
|
|
|
event->xconfigurerequest.value_mask &
|
|
|
|
CWBorderWidth ? "" : "(unset)");
|
2001-05-30 15:36:31 +00:00
|
|
|
break;
|
|
|
|
case GravityNotify:
|
|
|
|
name = "GravityNotify";
|
|
|
|
break;
|
|
|
|
case ResizeRequest:
|
|
|
|
name = "ResizeRequest";
|
|
|
|
break;
|
|
|
|
case CirculateNotify:
|
|
|
|
name = "CirculateNotify";
|
|
|
|
break;
|
|
|
|
case CirculateRequest:
|
|
|
|
name = "CirculateRequest";
|
|
|
|
break;
|
|
|
|
case PropertyNotify:
|
2001-06-11 03:24:20 +00:00
|
|
|
{
|
|
|
|
char *str;
|
|
|
|
const char *state;
|
|
|
|
|
|
|
|
name = "PropertyNotify";
|
|
|
|
|
|
|
|
meta_error_trap_push (display);
|
|
|
|
str = XGetAtomName (display->xdisplay,
|
|
|
|
event->xproperty.atom);
|
|
|
|
meta_error_trap_pop (display);
|
|
|
|
|
|
|
|
if (event->xproperty.state == PropertyNewValue)
|
|
|
|
state = "PropertyNewValue";
|
|
|
|
else if (event->xproperty.state == PropertyDelete)
|
|
|
|
state = "PropertyDelete";
|
|
|
|
else
|
2001-06-18 06:11:53 +00:00
|
|
|
state = "???";
|
2001-06-11 03:24:20 +00:00
|
|
|
|
|
|
|
extra = g_strdup_printf ("atom: %s state: %s",
|
|
|
|
str ? str : "(unknown atom)",
|
|
|
|
state);
|
|
|
|
XFree (str);
|
|
|
|
}
|
2001-05-30 15:36:31 +00:00
|
|
|
break;
|
|
|
|
case SelectionClear:
|
|
|
|
name = "SelectionClear";
|
|
|
|
break;
|
|
|
|
case SelectionRequest:
|
|
|
|
name = "SelectionRequest";
|
|
|
|
break;
|
|
|
|
case SelectionNotify:
|
|
|
|
name = "SelectionNotify";
|
|
|
|
break;
|
|
|
|
case ColormapNotify:
|
|
|
|
name = "ColormapNotify";
|
|
|
|
break;
|
|
|
|
case ClientMessage:
|
2001-06-07 05:18:10 +00:00
|
|
|
{
|
|
|
|
char *str;
|
|
|
|
name = "ClientMessage";
|
|
|
|
meta_error_trap_push (display);
|
|
|
|
str = XGetAtomName (display->xdisplay,
|
|
|
|
event->xclient.message_type);
|
|
|
|
meta_error_trap_pop (display);
|
|
|
|
extra = g_strdup_printf ("type: %s format: %d\n",
|
|
|
|
str ? str : "(unknown atom)",
|
|
|
|
event->xclient.format);
|
|
|
|
XFree (str);
|
|
|
|
}
|
2001-05-30 15:36:31 +00:00
|
|
|
break;
|
|
|
|
case MappingNotify:
|
|
|
|
name = "MappingNotify";
|
|
|
|
break;
|
|
|
|
default:
|
2001-08-19 18:09:10 +00:00
|
|
|
meta_verbose ("Unknown event type %d\n", event->xany.type);
|
2001-06-23 05:26:28 +00:00
|
|
|
name = "Unknown event type";
|
2001-05-30 15:36:31 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
screen = meta_display_screen_for_root (display, event->xany.window);
|
|
|
|
|
|
|
|
if (screen)
|
|
|
|
winname = g_strdup_printf ("root %d", screen->number);
|
|
|
|
else
|
|
|
|
winname = g_strdup_printf ("0x%lx", event->xany.window);
|
|
|
|
|
2001-08-30 04:01:38 +00:00
|
|
|
meta_verbose ("%s on %s%s %s serial %lu\n", name, winname,
|
|
|
|
extra ? ":" : "", extra ? extra : "",
|
|
|
|
event->xany.serial);
|
2001-05-30 15:36:31 +00:00
|
|
|
|
|
|
|
g_free (winname);
|
|
|
|
|
|
|
|
if (extra)
|
|
|
|
g_free (extra);
|
|
|
|
}
|
|
|
|
|
|
|
|
MetaWindow*
|
2001-05-31 06:42:58 +00:00
|
|
|
meta_display_lookup_x_window (MetaDisplay *display,
|
|
|
|
Window xwindow)
|
2001-05-30 15:36:31 +00:00
|
|
|
{
|
|
|
|
return g_hash_table_lookup (display->window_ids, &xwindow);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2001-05-31 06:42:58 +00:00
|
|
|
meta_display_register_x_window (MetaDisplay *display,
|
|
|
|
Window *xwindowp,
|
|
|
|
MetaWindow *window)
|
2001-05-30 15:36:31 +00:00
|
|
|
{
|
2001-05-31 06:42:58 +00:00
|
|
|
g_return_if_fail (g_hash_table_lookup (display->window_ids, xwindowp) == NULL);
|
2001-05-30 15:36:31 +00:00
|
|
|
|
2001-05-31 06:42:58 +00:00
|
|
|
g_hash_table_insert (display->window_ids, xwindowp, window);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
meta_display_unregister_x_window (MetaDisplay *display,
|
|
|
|
Window xwindow)
|
|
|
|
{
|
|
|
|
g_return_if_fail (g_hash_table_lookup (display->window_ids, &xwindow) != NULL);
|
|
|
|
|
|
|
|
g_hash_table_remove (display->window_ids, &xwindow);
|
2001-05-30 15:36:31 +00:00
|
|
|
}
|
2001-06-06 04:47:37 +00:00
|
|
|
|
|
|
|
MetaWorkspace*
|
|
|
|
meta_display_get_workspace_by_index (MetaDisplay *display,
|
|
|
|
int index)
|
|
|
|
{
|
|
|
|
GList *tmp;
|
2001-08-03 13:56:39 +00:00
|
|
|
|
|
|
|
/* should be robust, index is maybe from an app */
|
|
|
|
if (index < 0)
|
|
|
|
return NULL;
|
2001-06-06 04:47:37 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
|
2001-08-03 13:56:39 +00:00
|
|
|
/* should be robust, index is maybe from an app */
|
|
|
|
if (index < 0)
|
|
|
|
return NULL;
|
|
|
|
|
2001-06-06 04:47:37 +00:00
|
|
|
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;
|
|
|
|
}
|
2001-07-11 06:22:00 +00:00
|
|
|
|
2001-07-26 03:14:45 +00:00
|
|
|
Cursor
|
|
|
|
meta_display_create_x_cursor (MetaDisplay *display,
|
|
|
|
MetaCursor cursor)
|
|
|
|
{
|
|
|
|
Cursor xcursor;
|
|
|
|
guint glyph;
|
|
|
|
|
|
|
|
switch (cursor)
|
|
|
|
{
|
|
|
|
case META_CURSOR_DEFAULT:
|
|
|
|
glyph = XC_left_ptr;
|
|
|
|
break;
|
|
|
|
case META_CURSOR_NORTH_RESIZE:
|
|
|
|
glyph = XC_top_side;
|
|
|
|
break;
|
|
|
|
case META_CURSOR_SOUTH_RESIZE:
|
|
|
|
glyph = XC_bottom_side;
|
|
|
|
break;
|
|
|
|
case META_CURSOR_WEST_RESIZE:
|
|
|
|
glyph = XC_left_side;
|
|
|
|
break;
|
|
|
|
case META_CURSOR_EAST_RESIZE:
|
|
|
|
glyph = XC_right_side;
|
|
|
|
break;
|
|
|
|
case META_CURSOR_SE_RESIZE:
|
|
|
|
glyph = XC_bottom_right_corner;
|
|
|
|
break;
|
|
|
|
case META_CURSOR_SW_RESIZE:
|
|
|
|
glyph = XC_bottom_left_corner;
|
|
|
|
break;
|
|
|
|
case META_CURSOR_NE_RESIZE:
|
|
|
|
glyph = XC_top_left_corner;
|
|
|
|
break;
|
|
|
|
case META_CURSOR_NW_RESIZE:
|
|
|
|
glyph = XC_top_right_corner;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
g_assert_not_reached ();
|
|
|
|
glyph = 0; /* silence compiler */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
xcursor = XCreateFontCursor (display->xdisplay, glyph);
|
|
|
|
|
|
|
|
return xcursor;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Cursor
|
|
|
|
xcursor_for_op (MetaDisplay *display,
|
|
|
|
MetaGrabOp op)
|
|
|
|
{
|
|
|
|
MetaCursor cursor = META_CURSOR_DEFAULT;
|
|
|
|
|
|
|
|
switch (display->grab_op)
|
|
|
|
{
|
|
|
|
case META_GRAB_OP_RESIZING_SE:
|
|
|
|
cursor = META_CURSOR_SE_RESIZE;
|
|
|
|
break;
|
|
|
|
case META_GRAB_OP_RESIZING_S:
|
|
|
|
cursor = META_CURSOR_SOUTH_RESIZE;
|
|
|
|
break;
|
|
|
|
case META_GRAB_OP_RESIZING_SW:
|
|
|
|
cursor = META_CURSOR_SW_RESIZE;
|
|
|
|
break;
|
|
|
|
case META_GRAB_OP_RESIZING_N:
|
|
|
|
cursor = META_CURSOR_NORTH_RESIZE;
|
|
|
|
break;
|
|
|
|
case META_GRAB_OP_RESIZING_NE:
|
|
|
|
cursor = META_CURSOR_NE_RESIZE;
|
|
|
|
break;
|
|
|
|
case META_GRAB_OP_RESIZING_NW:
|
|
|
|
cursor = META_CURSOR_NW_RESIZE;
|
|
|
|
break;
|
|
|
|
case META_GRAB_OP_RESIZING_W:
|
|
|
|
cursor = META_CURSOR_WEST_RESIZE;
|
|
|
|
break;
|
|
|
|
case META_GRAB_OP_RESIZING_E:
|
|
|
|
cursor = META_CURSOR_EAST_RESIZE;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return meta_display_create_x_cursor (display, cursor);
|
|
|
|
}
|
|
|
|
|
2001-07-11 06:22:00 +00:00
|
|
|
gboolean
|
|
|
|
meta_display_begin_grab_op (MetaDisplay *display,
|
|
|
|
MetaWindow *window,
|
|
|
|
MetaGrabOp op,
|
|
|
|
gboolean pointer_already_grabbed,
|
|
|
|
int button,
|
|
|
|
gulong modmask,
|
|
|
|
Time timestamp,
|
|
|
|
int root_x,
|
|
|
|
int root_y)
|
|
|
|
{
|
|
|
|
Window grabwindow;
|
2001-07-26 03:14:45 +00:00
|
|
|
Cursor cursor;
|
|
|
|
|
2001-07-11 06:22:00 +00:00
|
|
|
meta_verbose ("Doing grab op %d on window %s button %d pointer already grabbed: %d\n",
|
|
|
|
op, window->desc, button, pointer_already_grabbed);
|
|
|
|
|
|
|
|
grabwindow = window->frame ? window->frame->xwindow : window->xwindow;
|
|
|
|
|
|
|
|
if (display->grab_op != META_GRAB_OP_NONE)
|
|
|
|
{
|
|
|
|
meta_warning ("Attempt to perform window operation %d on window %s when operation %d on %s already in effect\n",
|
|
|
|
op, window->desc, display->grab_op, display->grab_window->desc);
|
|
|
|
return FALSE;
|
|
|
|
}
|
2001-07-26 03:14:45 +00:00
|
|
|
|
2001-07-11 06:22:00 +00:00
|
|
|
if (pointer_already_grabbed)
|
2001-07-26 03:14:45 +00:00
|
|
|
display->grab_have_pointer = TRUE;
|
|
|
|
|
2001-08-19 18:09:10 +00:00
|
|
|
/* We XGrabPointer even if we already have an autograb,
|
|
|
|
* just to set the cursor and event mask
|
|
|
|
*/
|
2001-07-26 03:14:45 +00:00
|
|
|
|
|
|
|
cursor = xcursor_for_op (display, op);
|
|
|
|
|
|
|
|
meta_error_trap_push (display);
|
|
|
|
if (XGrabPointer (display->xdisplay,
|
|
|
|
grabwindow,
|
|
|
|
False,
|
|
|
|
PointerMotionMask | PointerMotionHintMask |
|
|
|
|
ButtonPressMask | ButtonReleaseMask |
|
|
|
|
KeyPressMask | KeyReleaseMask,
|
|
|
|
GrabModeAsync, GrabModeAsync,
|
|
|
|
None,
|
|
|
|
cursor,
|
|
|
|
timestamp) == GrabSuccess)
|
2001-08-29 04:16:30 +00:00
|
|
|
{
|
|
|
|
display->grab_have_pointer = TRUE;
|
|
|
|
meta_debug_spew ("Successful XGrabPointer()\n");
|
|
|
|
}
|
2001-07-26 03:14:45 +00:00
|
|
|
meta_error_trap_pop (display);
|
|
|
|
|
|
|
|
XFreeCursor (display->xdisplay, cursor);
|
2001-07-11 06:22:00 +00:00
|
|
|
|
|
|
|
if (!display->grab_have_pointer)
|
|
|
|
{
|
|
|
|
meta_verbose ("XGrabPointer() failed\n");
|
|
|
|
return FALSE;
|
|
|
|
}
|
2001-08-19 18:09:10 +00:00
|
|
|
|
|
|
|
if (grab_op_is_keyboard (op))
|
2001-07-11 06:22:00 +00:00
|
|
|
{
|
|
|
|
if (meta_window_grab_all_keys (window))
|
|
|
|
display->grab_have_keyboard = TRUE;
|
2001-08-19 18:09:10 +00:00
|
|
|
|
2001-07-11 06:22:00 +00:00
|
|
|
if (!display->grab_have_keyboard)
|
|
|
|
{
|
2001-08-19 18:09:10 +00:00
|
|
|
meta_verbose ("grabbing all keys failed\n");
|
2001-07-11 06:22:00 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
2001-08-19 18:09:10 +00:00
|
|
|
|
2001-07-11 06:22:00 +00:00
|
|
|
display->grab_op = op;
|
|
|
|
display->grab_window = window;
|
|
|
|
display->grab_button = button;
|
|
|
|
display->grab_root_x = root_x;
|
|
|
|
display->grab_root_y = root_y;
|
2001-09-11 02:57:05 +00:00
|
|
|
display->grab_initial_window_pos = display->grab_window->rect;
|
2001-07-12 05:53:56 +00:00
|
|
|
meta_window_get_position (display->grab_window,
|
|
|
|
&display->grab_initial_window_pos.x,
|
|
|
|
&display->grab_initial_window_pos.y);
|
|
|
|
|
2001-07-11 06:22:00 +00:00
|
|
|
meta_verbose ("Grab op %d on window %s successful\n",
|
|
|
|
display->grab_op, display->grab_window->desc);
|
|
|
|
|
|
|
|
g_assert (display->grab_window != NULL);
|
|
|
|
g_assert (display->grab_op != META_GRAB_OP_NONE);
|
2001-08-19 18:09:10 +00:00
|
|
|
|
|
|
|
/* Do this last, after everything is set up. */
|
|
|
|
if (op == META_GRAB_OP_KEYBOARD_TABBING)
|
|
|
|
meta_screen_ensure_tab_popup (window->screen);
|
2001-07-11 06:22:00 +00:00
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
meta_display_end_grab_op (MetaDisplay *display,
|
|
|
|
Time timestamp)
|
|
|
|
{
|
|
|
|
if (display->grab_op == META_GRAB_OP_NONE)
|
|
|
|
return;
|
2001-08-19 18:09:10 +00:00
|
|
|
|
|
|
|
if (display->grab_op == META_GRAB_OP_KEYBOARD_TABBING)
|
|
|
|
{
|
|
|
|
meta_ui_tab_popup_free (display->grab_window->screen->tab_popup);
|
|
|
|
display->grab_window->screen->tab_popup = NULL;
|
|
|
|
}
|
2001-07-11 06:22:00 +00:00
|
|
|
|
|
|
|
if (display->grab_have_pointer)
|
|
|
|
XUngrabPointer (display->xdisplay, timestamp);
|
|
|
|
|
|
|
|
if (display->grab_have_keyboard)
|
|
|
|
meta_window_ungrab_all_keys (display->grab_window);
|
2001-07-26 03:14:45 +00:00
|
|
|
|
2001-07-11 06:22:00 +00:00
|
|
|
display->grab_window = NULL;
|
2001-07-26 03:14:45 +00:00
|
|
|
display->grab_op = META_GRAB_OP_NONE;
|
|
|
|
}
|
|
|
|
|
2001-10-26 04:00:38 +00:00
|
|
|
#define IGNORED_MODIFIERS (LockMask | Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask)
|
|
|
|
#define INTERESTING_MODIFIERS (~IGNORED_MODIFIERS)
|
|
|
|
|
|
|
|
static void
|
|
|
|
meta_change_button_grab (MetaDisplay *display,
|
|
|
|
Window xwindow,
|
|
|
|
gboolean grab,
|
|
|
|
int button,
|
|
|
|
int modmask)
|
|
|
|
{
|
|
|
|
int ignored_mask;
|
|
|
|
|
|
|
|
g_return_if_fail ((modmask & INTERESTING_MODIFIERS) == modmask);
|
|
|
|
|
|
|
|
ignored_mask = 0;
|
|
|
|
while (ignored_mask < IGNORED_MODIFIERS)
|
|
|
|
{
|
|
|
|
int result;
|
|
|
|
|
|
|
|
if (ignored_mask & INTERESTING_MODIFIERS)
|
|
|
|
{
|
|
|
|
/* Not a combination of IGNORED_MODIFIERS
|
|
|
|
* (it contains some non-ignored modifiers)
|
|
|
|
*/
|
|
|
|
++ignored_mask;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
meta_error_trap_push (display);
|
|
|
|
if (grab)
|
|
|
|
XGrabButton (display->xdisplay, button, modmask | ignored_mask,
|
|
|
|
xwindow, False,
|
|
|
|
ButtonPressMask | ButtonReleaseMask |
|
|
|
|
PointerMotionMask | PointerMotionHintMask,
|
|
|
|
GrabModeAsync, GrabModeAsync,
|
|
|
|
False, None);
|
|
|
|
else
|
|
|
|
XUngrabButton (display->xdisplay, button, modmask | ignored_mask,
|
|
|
|
xwindow);
|
|
|
|
|
|
|
|
result = meta_error_trap_pop (display);
|
|
|
|
|
|
|
|
if (result != Success)
|
|
|
|
meta_warning ("Failed to grab button %d with mask 0x%x for window 0x%lx error code %d\n",
|
|
|
|
button, modmask | ignored_mask, xwindow, result);
|
|
|
|
|
|
|
|
++ignored_mask;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-07-26 03:14:45 +00:00
|
|
|
void
|
|
|
|
meta_display_grab_window_buttons (MetaDisplay *display,
|
|
|
|
Window xwindow)
|
|
|
|
{
|
|
|
|
/* Grab Alt + button1 and Alt + button2 for moving window,
|
|
|
|
* and Alt + button3 for popping up window menu.
|
|
|
|
*/
|
2001-07-26 03:58:24 +00:00
|
|
|
meta_verbose ("Grabbing window buttons for 0x%lx\n", xwindow);
|
2001-08-19 18:09:10 +00:00
|
|
|
|
|
|
|
/* FIXME If we ignored errors here instead of spewing, we could
|
|
|
|
* put one big error trap around the loop and avoid a bunch of
|
|
|
|
* XSync()
|
|
|
|
*/
|
2001-07-26 03:58:24 +00:00
|
|
|
|
2001-07-26 03:14:45 +00:00
|
|
|
{
|
2001-10-26 04:00:38 +00:00
|
|
|
gboolean debug = g_getenv ("METACITY_DEBUG_BUTTON_GRABS") != NULL;
|
2001-07-26 03:14:45 +00:00
|
|
|
int i = 1;
|
|
|
|
while (i < 4)
|
|
|
|
{
|
2001-10-26 04:00:38 +00:00
|
|
|
meta_change_button_grab (display,
|
|
|
|
xwindow,
|
|
|
|
TRUE,
|
|
|
|
i, Mod1Mask);
|
|
|
|
|
|
|
|
|
|
|
|
/* This is for debugging, since I end up moving the Xnest
|
|
|
|
* otherwise ;-)
|
2001-10-14 04:11:42 +00:00
|
|
|
*/
|
2001-10-26 04:00:38 +00:00
|
|
|
if (debug)
|
|
|
|
meta_change_button_grab (display, xwindow,
|
|
|
|
TRUE,
|
|
|
|
i, ControlMask);
|
2001-07-26 03:14:45 +00:00
|
|
|
|
|
|
|
++i;
|
|
|
|
}
|
|
|
|
}
|
2001-07-11 06:22:00 +00:00
|
|
|
}
|
2001-07-26 03:14:45 +00:00
|
|
|
|
|
|
|
void
|
|
|
|
meta_display_ungrab_window_buttons (MetaDisplay *display,
|
|
|
|
Window xwindow)
|
|
|
|
{
|
2001-10-26 04:00:38 +00:00
|
|
|
gboolean debug = g_getenv ("METACITY_DEBUG_BUTTON_GRABS") != NULL;
|
2001-08-19 18:09:10 +00:00
|
|
|
int i = 1;
|
|
|
|
while (i < 4)
|
|
|
|
{
|
2001-10-26 04:00:38 +00:00
|
|
|
meta_change_button_grab (display, xwindow,
|
|
|
|
FALSE, i, Mod1Mask);
|
|
|
|
if (debug)
|
|
|
|
meta_change_button_grab (display, xwindow,
|
|
|
|
FALSE, i, ControlMask);
|
2001-08-19 18:09:10 +00:00
|
|
|
|
|
|
|
++i;
|
|
|
|
}
|
2001-07-26 03:14:45 +00:00
|
|
|
}
|
|
|
|
|
2001-08-30 04:01:38 +00:00
|
|
|
void
|
|
|
|
meta_display_increment_event_serial (MetaDisplay *display)
|
|
|
|
{
|
|
|
|
/* We just make some random X request */
|
|
|
|
XDeleteProperty (display->xdisplay, display->leader_window,
|
|
|
|
display->atom_motif_wm_hints);
|
|
|
|
}
|
2001-10-07 23:06:19 +00:00
|
|
|
|
|
|
|
void
|
|
|
|
meta_display_update_active_window_hint (MetaDisplay *display)
|
|
|
|
{
|
|
|
|
GSList *tmp;
|
|
|
|
|
|
|
|
unsigned long data[2];
|
|
|
|
|
|
|
|
if (display->focus_window)
|
|
|
|
data[0] = display->focus_window->xwindow;
|
|
|
|
else
|
|
|
|
data[0] = None;
|
|
|
|
data[1] = None;
|
|
|
|
|
|
|
|
tmp = display->screens;
|
|
|
|
while (tmp != NULL)
|
|
|
|
{
|
|
|
|
MetaScreen *screen = tmp->data;
|
|
|
|
|
|
|
|
meta_error_trap_push (display);
|
|
|
|
XChangeProperty (display->xdisplay, screen->xroot,
|
|
|
|
display->atom_net_active_window,
|
|
|
|
XA_WINDOW,
|
|
|
|
32, PropModeReplace, (guchar*) data, 2);
|
|
|
|
meta_error_trap_pop (display);
|
|
|
|
|
|
|
|
tmp = tmp->next;
|
|
|
|
}
|
|
|
|
}
|
2001-10-15 03:39:41 +00:00
|
|
|
|
|
|
|
static void
|
|
|
|
queue_windows_showing (MetaDisplay *display)
|
|
|
|
{
|
|
|
|
GSList *windows;
|
|
|
|
GSList *tmp;
|
|
|
|
|
|
|
|
windows = meta_display_list_windows (display);
|
|
|
|
|
|
|
|
tmp = windows;
|
|
|
|
while (tmp != NULL)
|
|
|
|
{
|
|
|
|
meta_window_queue_calc_showing (tmp->data);
|
|
|
|
|
|
|
|
tmp = tmp->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_slist_free (windows);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
meta_display_show_desktop (MetaDisplay *display)
|
|
|
|
{
|
|
|
|
|
|
|
|
if (display->showing_desktop)
|
|
|
|
return;
|
|
|
|
|
|
|
|
display->showing_desktop = TRUE;
|
|
|
|
|
|
|
|
queue_windows_showing (display);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
meta_display_unshow_desktop (MetaDisplay *display)
|
|
|
|
{
|
|
|
|
if (!display->showing_desktop)
|
|
|
|
return;
|
|
|
|
|
|
|
|
display->showing_desktop = FALSE;
|
|
|
|
|
|
|
|
queue_windows_showing (display);
|
|
|
|
}
|