summaryrefslogtreecommitdiff
path: root/src/core/core.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/core.c')
-rw-r--r--src/core/core.c779
1 files changed, 779 insertions, 0 deletions
diff --git a/src/core/core.c b/src/core/core.c
new file mode 100644
index 00000000..963cbfa7
--- /dev/null
+++ b/src/core/core.c
@@ -0,0 +1,779 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+
+/* Marco interface used by GTK+ UI to talk to core */
+
+/*
+ * Copyright (C) 2001 Havoc Pennington
+ * Copyright (C) 2003 Rob Adams
+ * Copyright (C) 2004-2006 Elijah Newren
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include <config.h>
+#include "core.h"
+#include "frame-private.h"
+#include "workspace.h"
+#include "prefs.h"
+
+/* Looks up the MetaWindow representing the frame of the given X window.
+ * Used as a helper function by a bunch of the functions below.
+ *
+ * FIXME: The functions that use this function throw the result away
+ * after use. Many of these functions tend to be called in small groups,
+ * which results in get_window() getting called several times in succession
+ * with the same parameters. We should profile to see whether this wastes
+ * much time, and if it does we should look into a generalised
+ * meta_core_get_window_info() which takes a bunch of pointers to variables
+ * to put its results in, and only fills in the non-null ones.
+ */
+static MetaWindow *
+get_window (Display *xdisplay,
+ Window frame_xwindow)
+{
+ MetaDisplay *display;
+ MetaWindow *window;
+
+ display = meta_display_for_x_display (xdisplay);
+ window = meta_display_lookup_x_window (display, frame_xwindow);
+
+ if (window == NULL || window->frame == NULL)
+ {
+ meta_bug ("No such frame window 0x%lx!\n", frame_xwindow);
+ return NULL;
+ }
+
+ return window;
+}
+
+void
+meta_core_get (Display *xdisplay,
+ Window xwindow,
+ ...)
+{
+ va_list args;
+ MetaCoreGetType request;
+
+ MetaDisplay *display = meta_display_for_x_display (xdisplay);
+ MetaWindow *window = meta_display_lookup_x_window (display, xwindow);
+
+ va_start (args, xwindow);
+
+ request = va_arg (args, MetaCoreGetType);
+
+ /* Now, we special-case the first request slightly. Mostly, requests
+ * for information on windows which have no frame are errors.
+ * But sometimes we may want to know *whether* a window has a frame.
+ * In this case, pass the key META_CORE_WINDOW_HAS_FRAME
+ * as the *first* request, with a pointer to a boolean; if the window
+ * has no frame, this will be set to False and meta_core_get will
+ * exit immediately (so the values of any other requests will be
+ * undefined). Otherwise it will be set to True and meta_core_get will
+ * continue happily on its way.
+ */
+
+ if (request != META_CORE_WINDOW_HAS_FRAME &&
+ (window == NULL || window->frame == NULL)) {
+ meta_bug ("No such frame window 0x%lx!\n", xwindow);
+ return;
+ }
+
+ while (request != META_CORE_GET_END) {
+
+ gpointer answer = va_arg (args, gpointer);
+
+ switch (request) {
+ case META_CORE_WINDOW_HAS_FRAME:
+ *((gboolean*)answer) = window != NULL && window->frame != NULL;
+ if (!*((gboolean*)answer)) return; /* see above */
+ break;
+ case META_CORE_GET_CLIENT_WIDTH:
+ *((gint*)answer) = window->rect.width;
+ break;
+ case META_CORE_GET_CLIENT_HEIGHT:
+ *((gint*)answer) = window->rect.height;
+ break;
+ case META_CORE_IS_TITLEBAR_ONSCREEN:
+ *((gboolean*)answer) = meta_window_titlebar_is_onscreen (window);
+ break;
+ case META_CORE_GET_CLIENT_XWINDOW:
+ *((Window*)answer) = window->xwindow;
+ break;
+ case META_CORE_GET_FRAME_FLAGS:
+ *((MetaFrameFlags*)answer) = meta_frame_get_flags (window->frame);
+ break;
+ case META_CORE_GET_FRAME_TYPE:
+ {
+ MetaFrameType base_type = META_FRAME_TYPE_LAST;
+
+ switch (window->type)
+ {
+ case META_WINDOW_NORMAL:
+ base_type = META_FRAME_TYPE_NORMAL;
+ break;
+
+ case META_WINDOW_DIALOG:
+ base_type = META_FRAME_TYPE_DIALOG;
+ break;
+
+ case META_WINDOW_MODAL_DIALOG:
+ base_type = META_FRAME_TYPE_MODAL_DIALOG;
+ break;
+
+ case META_WINDOW_MENU:
+ base_type = META_FRAME_TYPE_MENU;
+ break;
+
+ case META_WINDOW_UTILITY:
+ base_type = META_FRAME_TYPE_UTILITY;
+ break;
+
+ case META_WINDOW_DESKTOP:
+ case META_WINDOW_DOCK:
+ case META_WINDOW_TOOLBAR:
+ case META_WINDOW_SPLASHSCREEN:
+ /* No frame */
+ base_type = META_FRAME_TYPE_LAST;
+ break;
+
+ }
+
+ if (base_type == META_FRAME_TYPE_LAST)
+ {
+ /* can't add border if undecorated */
+ *((MetaFrameType*)answer) = META_FRAME_TYPE_LAST;
+ }
+ else if (window->border_only)
+ {
+ /* override base frame type */
+ *((MetaFrameType*)answer) = META_FRAME_TYPE_BORDER;
+ }
+ else
+ {
+ *((MetaFrameType*)answer) = base_type;
+ }
+
+ break;
+ }
+ case META_CORE_GET_MINI_ICON:
+ *((GdkPixbuf**)answer) = window->mini_icon;
+ break;
+ case META_CORE_GET_ICON:
+ *((GdkPixbuf**)answer) = window->icon;
+ break;
+ case META_CORE_GET_X:
+ meta_window_get_position (window, (int*)answer, NULL);
+ break;
+ case META_CORE_GET_Y:
+ meta_window_get_position (window, NULL, (int*)answer);
+ break;
+ case META_CORE_GET_FRAME_WORKSPACE:
+ *((gint*)answer) = meta_window_get_net_wm_desktop (window);
+ break;
+ case META_CORE_GET_FRAME_X:
+ *((gint*)answer) = window->frame->rect.x;
+ break;
+ case META_CORE_GET_FRAME_Y:
+ *((gint*)answer) = window->frame->rect.y;
+ break;
+ case META_CORE_GET_FRAME_WIDTH:
+ *((gint*)answer) = window->frame->rect.width;
+ break;
+ case META_CORE_GET_FRAME_HEIGHT:
+ *((gint*)answer) = window->frame->rect.height;
+ break;
+ case META_CORE_GET_SCREEN_WIDTH:
+ *((gint*)answer) = window->screen->rect.width;
+ break;
+ case META_CORE_GET_SCREEN_HEIGHT:
+ *((gint*)answer) = window->screen->rect.height;
+ break;
+
+ default:
+ meta_warning(_("Unknown window information request: %d"), request);
+ }
+
+ request = va_arg (args, MetaCoreGetType);
+ }
+
+ va_end (args);
+}
+
+void
+meta_core_queue_frame_resize (Display *xdisplay,
+ Window frame_xwindow)
+{
+ MetaWindow *window = get_window (xdisplay, frame_xwindow);
+
+ meta_window_queue (window, META_QUEUE_MOVE_RESIZE);
+}
+
+void
+meta_core_user_move (Display *xdisplay,
+ Window frame_xwindow,
+ int x,
+ int y)
+{
+ MetaWindow *window = get_window (xdisplay, frame_xwindow);
+
+ meta_window_move (window, TRUE, x, y);
+}
+
+void
+meta_core_user_resize (Display *xdisplay,
+ Window frame_xwindow,
+ int gravity,
+ int width,
+ int height)
+{
+ MetaWindow *window = get_window (xdisplay, frame_xwindow);
+
+ meta_window_resize_with_gravity (window, TRUE, width, height, gravity);
+}
+
+void
+meta_core_user_raise (Display *xdisplay,
+ Window frame_xwindow)
+{
+ MetaWindow *window = get_window (xdisplay, frame_xwindow);
+
+ meta_window_raise (window);
+}
+
+void
+meta_core_user_lower_and_unfocus (Display *xdisplay,
+ Window frame_xwindow,
+ guint32 timestamp)
+{
+ MetaWindow *window = get_window (xdisplay, frame_xwindow);
+
+ meta_window_lower (window);
+
+ if (meta_prefs_get_focus_mode () == META_FOCUS_MODE_CLICK &&
+ meta_prefs_get_raise_on_click ())
+ {
+ /* Move window to the back of the focusing workspace's MRU list.
+ * Do extra sanity checks to avoid possible race conditions.
+ * (Borrowed from window.c.)
+ */
+ if (window->screen->active_workspace &&
+ meta_window_located_on_workspace (window,
+ window->screen->active_workspace))
+ {
+ GList* link;
+ link = g_list_find (window->screen->active_workspace->mru_list,
+ window);
+ g_assert (link);
+
+ window->screen->active_workspace->mru_list =
+ g_list_remove_link (window->screen->active_workspace->mru_list,
+ link);
+ g_list_free (link);
+
+ window->screen->active_workspace->mru_list =
+ g_list_append (window->screen->active_workspace->mru_list,
+ window);
+ }
+ }
+
+ /* focus the default window, if needed */
+ if (window->has_focus)
+ meta_workspace_focus_default_window (window->screen->active_workspace,
+ NULL,
+ timestamp);
+}
+
+void
+meta_core_user_focus (Display *xdisplay,
+ Window frame_xwindow,
+ guint32 timestamp)
+{
+ MetaWindow *window = get_window (xdisplay, frame_xwindow);
+
+ meta_window_focus (window, timestamp);
+}
+
+void
+meta_core_minimize (Display *xdisplay,
+ Window frame_xwindow)
+{
+ MetaWindow *window = get_window (xdisplay, frame_xwindow);
+
+ meta_window_minimize (window);
+}
+
+void
+meta_core_maximize (Display *xdisplay,
+ Window frame_xwindow)
+{
+ MetaWindow *window = get_window (xdisplay, frame_xwindow);
+
+ if (meta_prefs_get_raise_on_click ())
+ meta_window_raise (window);
+
+ meta_window_maximize (window,
+ META_MAXIMIZE_HORIZONTAL | META_MAXIMIZE_VERTICAL);
+}
+
+void
+meta_core_toggle_maximize_vertically (Display *xdisplay,
+ Window frame_xwindow)
+{
+ MetaWindow *window = get_window (xdisplay, frame_xwindow);
+
+ if (meta_prefs_get_raise_on_click ())
+ meta_window_raise (window);
+
+ if (META_WINDOW_MAXIMIZED_VERTICALLY (window))
+ meta_window_unmaximize (window,
+ META_MAXIMIZE_VERTICAL);
+ else
+ meta_window_maximize (window,
+ META_MAXIMIZE_VERTICAL);
+}
+
+void
+meta_core_toggle_maximize_horizontally (Display *xdisplay,
+ Window frame_xwindow)
+{
+ MetaWindow *window = get_window (xdisplay, frame_xwindow);
+
+ if (meta_prefs_get_raise_on_click ())
+ meta_window_raise (window);
+
+ if (META_WINDOW_MAXIMIZED_HORIZONTALLY (window))
+ meta_window_unmaximize (window,
+ META_MAXIMIZE_HORIZONTAL);
+ else
+ meta_window_maximize (window,
+ META_MAXIMIZE_HORIZONTAL);
+}
+
+void
+meta_core_toggle_maximize (Display *xdisplay,
+ Window frame_xwindow)
+{
+ MetaWindow *window = get_window (xdisplay, frame_xwindow);
+
+ if (meta_prefs_get_raise_on_click ())
+ meta_window_raise (window);
+
+ if (META_WINDOW_MAXIMIZED (window))
+ meta_window_unmaximize (window,
+ META_MAXIMIZE_HORIZONTAL | META_MAXIMIZE_VERTICAL);
+ else
+ meta_window_maximize (window,
+ META_MAXIMIZE_HORIZONTAL | META_MAXIMIZE_VERTICAL);
+}
+
+void
+meta_core_unmaximize (Display *xdisplay,
+ Window frame_xwindow)
+{
+ MetaWindow *window = get_window (xdisplay, frame_xwindow);
+
+ if (meta_prefs_get_raise_on_click ())
+ meta_window_raise (window);
+
+ meta_window_unmaximize (window,
+ META_MAXIMIZE_HORIZONTAL | META_MAXIMIZE_VERTICAL);
+}
+
+void
+meta_core_delete (Display *xdisplay,
+ Window frame_xwindow,
+ guint32 timestamp)
+{
+ MetaWindow *window = get_window (xdisplay, frame_xwindow);
+
+ meta_window_delete (window, timestamp);
+}
+
+void
+meta_core_unshade (Display *xdisplay,
+ Window frame_xwindow,
+ guint32 timestamp)
+{
+ MetaWindow *window = get_window (xdisplay, frame_xwindow);
+
+ meta_window_unshade (window, timestamp);
+}
+
+void
+meta_core_shade (Display *xdisplay,
+ Window frame_xwindow,
+ guint32 timestamp)
+{
+ MetaWindow *window = get_window (xdisplay, frame_xwindow);
+
+ meta_window_shade (window, timestamp);
+}
+
+void
+meta_core_unstick (Display *xdisplay,
+ Window frame_xwindow)
+{
+ MetaWindow *window = get_window (xdisplay, frame_xwindow);
+
+ meta_window_unstick (window);
+}
+
+void
+meta_core_make_above (Display *xdisplay,
+ Window frame_xwindow)
+{
+ MetaWindow *window = get_window (xdisplay, frame_xwindow);
+
+ meta_window_make_above (window);
+}
+
+void
+meta_core_unmake_above (Display *xdisplay,
+ Window frame_xwindow)
+{
+ MetaWindow *window = get_window (xdisplay, frame_xwindow);
+
+ meta_window_unmake_above (window);
+}
+
+void
+meta_core_stick (Display *xdisplay,
+ Window frame_xwindow)
+{
+ MetaWindow *window = get_window (xdisplay, frame_xwindow);
+
+ meta_window_stick (window);
+}
+
+void
+meta_core_change_workspace (Display *xdisplay,
+ Window frame_xwindow,
+ int new_workspace)
+{
+ MetaWindow *window = get_window (xdisplay, frame_xwindow);
+
+ meta_window_change_workspace (window,
+ meta_screen_get_workspace_by_index (window->screen,
+ new_workspace));
+}
+
+int
+meta_core_get_num_workspaces (Screen *xscreen)
+{
+ MetaScreen *screen;
+
+ screen = meta_screen_for_x_screen (xscreen);
+
+ return meta_screen_get_n_workspaces (screen);
+}
+
+int
+meta_core_get_active_workspace (Screen *xscreen)
+{
+ MetaScreen *screen;
+
+ screen = meta_screen_for_x_screen (xscreen);
+
+ return meta_workspace_index (screen->active_workspace);
+}
+
+void
+meta_core_show_window_menu (Display *xdisplay,
+ Window frame_xwindow,
+ int root_x,
+ int root_y,
+ int button,
+ guint32 timestamp)
+{
+ MetaWindow *window = get_window (xdisplay, frame_xwindow);
+
+ if (meta_prefs_get_raise_on_click ())
+ meta_window_raise (window);
+ meta_window_focus (window, timestamp);
+
+ meta_window_show_menu (window, root_x, root_y, button, timestamp);
+}
+
+void
+meta_core_get_menu_accelerator (MetaMenuOp menu_op,
+ int workspace,
+ unsigned int *keysym,
+ MetaVirtualModifier *modifiers)
+{
+ const char *name;
+
+ name = NULL;
+
+ switch (menu_op)
+ {
+ case META_MENU_OP_NONE:
+ /* No keybinding for this one */
+ break;
+ case META_MENU_OP_DELETE:
+ name = "close";
+ break;
+ case META_MENU_OP_MINIMIZE:
+ name = "minimize";
+ break;
+ case META_MENU_OP_UNMAXIMIZE:
+ name = "unmaximize";
+ break;
+ case META_MENU_OP_MAXIMIZE:
+ name = "maximize";
+ break;
+ case META_MENU_OP_UNSHADE:
+ case META_MENU_OP_SHADE:
+ name = "toggle_shaded";
+ break;
+ case META_MENU_OP_UNSTICK:
+ case META_MENU_OP_STICK:
+ name = "toggle_on_all_workspaces";
+ break;
+ case META_MENU_OP_ABOVE:
+ case META_MENU_OP_UNABOVE:
+ name = "toggle_above";
+ break;
+ case META_MENU_OP_WORKSPACES:
+ switch (workspace)
+ {
+ case 1:
+ name = "move_to_workspace_1";
+ break;
+ case 2:
+ name = "move_to_workspace_2";
+ break;
+ case 3:
+ name = "move_to_workspace_3";
+ break;
+ case 4:
+ name = "move_to_workspace_4";
+ break;
+ case 5:
+ name = "move_to_workspace_5";
+ break;
+ case 6:
+ name = "move_to_workspace_6";
+ break;
+ case 7:
+ name = "move_to_workspace_7";
+ break;
+ case 8:
+ name = "move_to_workspace_8";
+ break;
+ case 9:
+ name = "move_to_workspace_9";
+ break;
+ case 10:
+ name = "move_to_workspace_10";
+ break;
+ case 11:
+ name = "move_to_workspace_11";
+ break;
+ case 12:
+ name = "move_to_workspace_12";
+ break;
+ }
+ break;
+ case META_MENU_OP_MOVE:
+ name = "begin_move";
+ break;
+ case META_MENU_OP_RESIZE:
+ name = "begin_resize";
+ break;
+ case META_MENU_OP_MOVE_LEFT:
+ name = "move_to_workspace_left";
+ break;
+ case META_MENU_OP_MOVE_RIGHT:
+ name = "move_to_workspace_right";
+ break;
+ case META_MENU_OP_MOVE_UP:
+ name = "move_to_workspace_up";
+ break;
+ case META_MENU_OP_MOVE_DOWN:
+ name = "move_to_workspace_down";
+ break;
+ case META_MENU_OP_RECOVER:
+ /* No keybinding for this one */
+ break;
+ }
+
+ if (name)
+ {
+ meta_prefs_get_window_binding (name, keysym, modifiers);
+ }
+ else
+ {
+ *keysym = 0;
+ *modifiers = 0;
+ }
+}
+
+const char*
+meta_core_get_workspace_name_with_index (Display *xdisplay,
+ Window xroot,
+ int index)
+{
+ MetaDisplay *display;
+ MetaScreen *screen;
+ MetaWorkspace *workspace;
+
+ display = meta_display_for_x_display (xdisplay);
+ screen = meta_display_screen_for_root (display, xroot);
+ g_assert (screen != NULL);
+ workspace = meta_screen_get_workspace_by_index (screen, index);
+ return workspace ? meta_workspace_get_name (workspace) : NULL;
+}
+
+gboolean
+meta_core_begin_grab_op (Display *xdisplay,
+ Window frame_xwindow,
+ MetaGrabOp op,
+ gboolean pointer_already_grabbed,
+ gboolean frame_action,
+ int button,
+ gulong modmask,
+ guint32 timestamp,
+ int root_x,
+ int root_y)
+{
+ MetaWindow *window = get_window (xdisplay, frame_xwindow);
+ MetaDisplay *display;
+ MetaScreen *screen;
+
+ display = meta_display_for_x_display (xdisplay);
+ screen = meta_display_screen_for_xwindow (display, frame_xwindow);
+
+ g_assert (screen != NULL);
+
+ return meta_display_begin_grab_op (display, screen, window,
+ op, pointer_already_grabbed,
+ frame_action,
+ button, modmask,
+ timestamp, root_x, root_y);
+}
+
+void
+meta_core_end_grab_op (Display *xdisplay,
+ guint32 timestamp)
+{
+ MetaDisplay *display;
+
+ display = meta_display_for_x_display (xdisplay);
+
+ meta_display_end_grab_op (display, timestamp);
+}
+
+MetaGrabOp
+meta_core_get_grab_op (Display *xdisplay)
+{
+ MetaDisplay *display;
+
+ display = meta_display_for_x_display (xdisplay);
+
+ return display->grab_op;
+}
+
+Window
+meta_core_get_grab_frame (Display *xdisplay)
+{
+ MetaDisplay *display;
+
+ display = meta_display_for_x_display (xdisplay);
+
+ g_assert (display != NULL);
+ g_assert (display->grab_op == META_GRAB_OP_NONE ||
+ display->grab_screen != NULL);
+ g_assert (display->grab_op == META_GRAB_OP_NONE ||
+ display->grab_screen->display->xdisplay == xdisplay);
+
+ if (display->grab_op != META_GRAB_OP_NONE &&
+ display->grab_window &&
+ display->grab_window->frame)
+ return display->grab_window->frame->xwindow;
+ else
+ return None;
+}
+
+int
+meta_core_get_grab_button (Display *xdisplay)
+{
+ MetaDisplay *display;
+
+ display = meta_display_for_x_display (xdisplay);
+
+ if (display->grab_op == META_GRAB_OP_NONE)
+ return -1;
+
+ return display->grab_button;
+}
+
+void
+meta_core_grab_buttons (Display *xdisplay,
+ Window frame_xwindow)
+{
+ MetaDisplay *display;
+
+ display = meta_display_for_x_display (xdisplay);
+
+ meta_verbose ("Grabbing buttons on frame 0x%lx\n", frame_xwindow);
+ meta_display_grab_window_buttons (display, frame_xwindow);
+}
+
+void
+meta_core_set_screen_cursor (Display *xdisplay,
+ Window frame_on_screen,
+ MetaCursor cursor)
+{
+ MetaWindow *window = get_window (xdisplay, frame_on_screen);
+
+ meta_frame_set_screen_cursor (window->frame, cursor);
+}
+
+void
+meta_core_increment_event_serial (Display *xdisplay)
+{
+ MetaDisplay *display;
+
+ display = meta_display_for_x_display (xdisplay);
+
+ meta_display_increment_event_serial (display);
+}
+
+void
+meta_invalidate_default_icons (void)
+{
+ MetaDisplay *display = meta_get_display ();
+ GSList *windows;
+ GSList *l;
+
+ if (display == NULL)
+ return; /* We can validly be called before the display is opened. */
+
+ windows = meta_display_list_windows (display);
+ for (l = windows; l != NULL; l = l->next)
+ {
+ MetaWindow *window = (MetaWindow*)l->data;
+
+ if (window->icon_cache.origin == USING_FALLBACK_ICON)
+ {
+ meta_icon_cache_free (&(window->icon_cache));
+ meta_window_update_icon_now (window);
+ }
+ }
+
+ g_slist_free (windows);
+}
+