diff options
Diffstat (limited to 'matchbox/mb-wm-root-window.c')
-rw-r--r-- | matchbox/mb-wm-root-window.c | 436 |
1 files changed, 436 insertions, 0 deletions
diff --git a/matchbox/mb-wm-root-window.c b/matchbox/mb-wm-root-window.c new file mode 100644 index 0000000..21b8617 --- /dev/null +++ b/matchbox/mb-wm-root-window.c @@ -0,0 +1,436 @@ +/* + * Matchbox Window Manager II - A lightweight window manager not for the + * desktop. + * + * Authored By Tomas Frydrych <tf@o-hand.com> + * + * Copyright (c) 2007 OpenedHand Ltd - http://o-hand.com + * + * 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, 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. + * + */ + +#include "matchbox.h" + +#include "mb-wm-theme.h" +#include "mb-wm-client-dialog.h" +#include "mb-wm-client-app.h" + +#include <X11/Xmd.h> + +static void +mb_wm_root_window_class_init (MBWMObjectClass *klass) +{ + MBWMRootWindowClass *rw_class; + + MBWM_MARK(); + + rw_class = (MBWMRootWindowClass *)klass; + +#if MBWM_WANT_DEBUG + klass->klass_name = "MBWMRootWindow"; +#endif +} + +static void +mb_wm_root_window_destroy (MBWMObject *this) +{ +} + +static Bool +mb_wm_root_window_init_attributes (MBWMRootWindow * win); + +static void +mb_wm_root_window_init_properties (MBWMRootWindow * win); + +static int +mb_wm_root_window_init (MBWMObject *this, va_list vap) +{ + MBWMRootWindow *root_window = MB_WM_ROOT_WINDOW (this); + MBWindowManager *wm; + MBWMObjectProp prop; + XSetWindowAttributes attr; + + prop = va_arg(vap, MBWMObjectProp); + while (prop) + { + if (prop == MBWMObjectPropWm) + { + wm = va_arg(vap, MBWindowManager *); + break; + } + else + MBWMO_PROP_EAT (vap, prop); + + prop = va_arg(vap, MBWMObjectProp); + } + + root_window->wm = wm; + root_window->xwindow = RootWindow(wm->xdpy, wm->xscreen); + + if (!mb_wm_root_window_init_attributes (root_window)) + { + MBWM_DBG ("Failed to initialize root window attributes."); + abort (); + } + + attr.override_redirect = True; + root_window->hidden_window = XCreateWindow(wm->xdpy, + root_window->xwindow, + -200, -200, 5, 5, 0, + CopyFromParent, + CopyFromParent, + CopyFromParent, + CWOverrideRedirect, &attr); + + mb_wm_root_window_init_properties (root_window); + + return 1; +} + +int +mb_wm_root_window_class_type () +{ + static int type = 0; + + if (UNLIKELY(type == 0)) + { + static MBWMObjectClassInfo info = { + sizeof (MBWMRootWindowClass), + sizeof (MBWMRootWindow), + mb_wm_root_window_init, + mb_wm_root_window_destroy, + mb_wm_root_window_class_init + }; + + type = mb_wm_object_register_class (&info, MB_WM_TYPE_OBJECT, 0); + } + + return type; +} + +MBWMRootWindow* +mb_wm_root_window_get (MBWindowManager *wm) +{ + static MBWMRootWindow * root_window = NULL; + + if (!root_window) + { + root_window + = MB_WM_ROOT_WINDOW (mb_wm_object_new (MB_WM_TYPE_ROOT_WINDOW, + MBWMObjectPropWm, wm, + NULL)); + } + else + mb_wm_object_ref (MB_WM_OBJECT (root_window)); + + return root_window; +} + +static Bool +mb_wm_root_window_init_attributes (MBWMRootWindow * win) +{ + XSetWindowAttributes sattr; + MBWindowManager *wm = win->wm; + + sattr.event_mask = SubstructureRedirectMask + |SubstructureNotifyMask + |StructureNotifyMask + |PropertyChangeMask; + + mb_wm_util_trap_x_errors(); + + XChangeWindowAttributes(wm->xdpy, win->xwindow, CWEventMask, &sattr); + + XSync(wm->xdpy, False); + + if (mb_wm_util_untrap_x_errors()) + { + /* FIXME: Error codes */ + mb_wm_util_fatal_error("Unable to manage display - " + "another window manager already active?"); + return False; + } + + XSelectInput(wm->xdpy, win->xwindow, sattr.event_mask); + + return True; +} + +void +mb_wm_root_window_update_supported_props (MBWMRootWindow *win) +{ + MBWindowManager *wm = win->wm; + Window rwin = win->xwindow; + CARD32 num_supported = 0; + + /* + * Supported info + */ + Atom supported[] = { + wm->atoms[MBWM_ATOM_NET_WM_WINDOW_TYPE_TOOLBAR], + wm->atoms[MBWM_ATOM_NET_WM_WINDOW_TYPE_DOCK], + wm->atoms[MBWM_ATOM_NET_WM_WINDOW_TYPE_DIALOG], + wm->atoms[MBWM_ATOM_NET_WM_WINDOW_TYPE_DESKTOP], + wm->atoms[MBWM_ATOM_NET_WM_WINDOW_TYPE_SPLASH], + wm->atoms[MBWM_ATOM_NET_WM_WINDOW_TYPE_MENU], + wm->atoms[MBWM_ATOM_NET_WM_STATE], + wm->atoms[MBWM_ATOM_NET_WM_STATE_FULLSCREEN], + wm->atoms[MBWM_ATOM_NET_WM_STATE_MODAL], + wm->atoms[MBWM_ATOM_NET_SUPPORTED], + wm->atoms[MBWM_ATOM_NET_CLIENT_LIST], + wm->atoms[MBWM_ATOM_NET_NUMBER_OF_DESKTOPS], + wm->atoms[MBWM_ATOM_NET_ACTIVE_WINDOW], + wm->atoms[MBWM_ATOM_NET_SUPPORTING_WM_CHECK], + wm->atoms[MBWM_ATOM_NET_CLOSE_WINDOW], + wm->atoms[MBWM_ATOM_NET_CURRENT_DESKTOP], + wm->atoms[MBWM_ATOM_NET_CLIENT_LIST_STACKING], + wm->atoms[MBWM_ATOM_NET_SHOWING_DESKTOP], + wm->atoms[MBWM_ATOM_NET_WM_NAME], + wm->atoms[MBWM_ATOM_NET_WM_ICON], + wm->atoms[MBWM_ATOM_NET_WM_ALLOWED_ACTIONS], + wm->atoms[MBWM_ATOM_NET_WM_ACTION_MOVE], + wm->atoms[MBWM_ATOM_NET_WM_ACTION_FULLSCREEN], + wm->atoms[MBWM_ATOM_NET_WM_ACTION_CLOSE], + wm->atoms[MBWM_ATOM_NET_STARTUP_ID], + wm->atoms[MBWM_ATOM_NET_WM_PING], + wm->atoms[MBWM_ATOM_NET_WORKAREA], + wm->atoms[MBWM_ATOM_NET_DESKTOP_GEOMETRY], + wm->atoms[MBWM_ATOM_NET_WM_PING], + wm->atoms[MBWM_ATOM_NET_WM_PID], + wm->atoms[MBWM_ATOM_CM_TRANSLUCENCY], + wm->atoms[MBWM_ATOM_NET_WM_FULL_PLACEMENT], + wm->atoms[MBWM_ATOM_NET_FRAME_EXTENTS], + 0, 0, 0 + }; + + num_supported = sizeof(supported)/sizeof(Atom) - 3; + + /* Check to see if the theme supports help / accept buttons */ + if (wm->theme) + { + if (mb_wm_theme_supports (wm->theme, + MBWMThemeCapsFrameMainButtonActionAccept)) + supported[num_supported++]=wm->atoms[MBWM_ATOM_NET_WM_CONTEXT_ACCEPT]; + + if (mb_wm_theme_supports (wm->theme, + MBWMThemeCapsFrameMainButtonActionHelp)) + supported[num_supported++] = wm->atoms[MBWM_ATOM_NET_WM_CONTEXT_HELP]; + + if (mb_wm_theme_supports (wm->theme, + MBWMThemeCapsFrameMainButtonActionCustom)) + supported[num_supported++]=wm->atoms[MBWM_ATOM_NET_WM_CONTEXT_CUSTOM]; + } + + XChangeProperty(wm->xdpy, rwin, wm->atoms[MBWM_ATOM_NET_SUPPORTED], + XA_ATOM, 32, PropModeReplace, (unsigned char *)supported, + num_supported); + + if (wm->theme) + { + if (wm->theme->path) + XChangeProperty(wm->xdpy, rwin, wm->atoms[MBWM_ATOM_MB_THEME], + XA_STRING, 8, PropModeReplace, + (unsigned char *)wm->theme->path, + strlen (wm->theme->path) + 1); + else + XDeleteProperty (wm->xdpy, rwin, wm->atoms[MBWM_ATOM_MB_THEME]); + } +} + +static void +mb_wm_root_window_init_properties (MBWMRootWindow * win) +{ + MBWindowManager *wm = win->wm; + Window rwin = win->xwindow; + Window hwin = win->hidden_window; + + CARD32 card32; + unsigned long val[2]; + char *app_name = "matchbox"; + + val[0] = hwin; + + /* Window name */ + XChangeProperty(wm->xdpy, hwin, + wm->atoms[MBWM_ATOM_NET_WM_NAME], + wm->atoms[MBWM_ATOM_UTF8_STRING], + 8, PropModeReplace, + (unsigned char *)app_name, strlen(app_name)+1); + + XStoreName(wm->xdpy, hwin, app_name); + + /* Crack Needed to stop gnome session hanging ? */ + XChangeProperty(wm->xdpy, rwin, + wm->atoms[MBWM_ATOM_WIN_SUPPORTING_WM_CHECK], + XA_WINDOW, 32, PropModeReplace, (unsigned char *)val, + 1); + + XChangeProperty(wm->xdpy, hwin, + wm->atoms[MBWM_ATOM_WIN_SUPPORTING_WM_CHECK], + XA_WINDOW, 32, PropModeReplace, + (unsigned char *)val, 1); + + /* Correct way of doing it */ + XChangeProperty(wm->xdpy, rwin, + wm->atoms[MBWM_ATOM_NET_SUPPORTING_WM_CHECK], + XA_WINDOW, 32, PropModeReplace, (unsigned char *)val, + 1); + + XChangeProperty(wm->xdpy, hwin, + wm->atoms[MBWM_ATOM_NET_SUPPORTING_WM_CHECK], + XA_WINDOW, 32, PropModeReplace, + (unsigned char *)val, 1); + + mb_wm_root_window_update_supported_props (win); + + /* + * Desktop info + */ + card32 = 1; + XChangeProperty(wm->xdpy, rwin, wm->atoms[MBWM_ATOM_NET_NUMBER_OF_DESKTOPS], + XA_CARDINAL, 32, PropModeReplace, + (unsigned char *)&card32, 1); + + --card32; + XChangeProperty(wm->xdpy, rwin, wm->atoms[MBWM_ATOM_NET_CURRENT_DESKTOP], + XA_CARDINAL, 32, PropModeReplace, + (unsigned char *)&card32, 1); + + XChangeProperty(wm->xdpy, rwin, wm->atoms[MBWM_ATOM_NET_SHOWING_DESKTOP], + XA_CARDINAL, 32, PropModeReplace, + (unsigned char *)&card32, 1); + + val[0] = 0; + val[1] = 0; + + XChangeProperty(wm->xdpy, rwin, wm->atoms[MBWM_ATOM_NET_DESKTOP_VIEWPORT], + XA_CARDINAL, 32, PropModeReplace, + (unsigned char *)&val[0], 2); + + XSync(wm->xdpy, False); +} + +int +mb_wm_root_window_handle_message (MBWMRootWindow *win, XClientMessageEvent *e) +{ + MBWindowManager *wm = win->wm; + MBWindowManagerClient *c = NULL; + + if (e->message_type == wm->atoms[MBWM_ATOM_NET_ACTIVE_WINDOW]) + { + Window xwin = e->window; + + if ((c = mb_wm_managed_client_from_xwindow (wm, xwin)) != NULL) + mb_wm_activate_client (wm, c); + + return 1; + } + else if (e->message_type == wm->atoms[MBWM_ATOM_NET_CLOSE_WINDOW]) + { + if ((c = mb_wm_managed_client_from_xwindow(wm, e->window)) != NULL) + mb_wm_client_deliver_delete(c); + + return 1; + } + else if (e->message_type == wm->atoms[MBWM_ATOM_WM_PROTOCOLS] + && e->data.l[0] == wm->atoms[MBWM_ATOM_NET_WM_PING]) + { + if ((c = mb_wm_managed_client_from_xwindow(wm, e->data.l[2])) != NULL) + mb_wm_handle_ping_reply (wm, c); + return 1; + } + else if (e->message_type == wm->atoms[MBWM_ATOM_NET_WM_STATE]) + { + MBWMClientWindowStateChange state_op = 0; + + if (e->data.l[0] == 0) + state_op = MBWMClientWindowStateChangeRemove; + else if (e->data.l[0] == 1) + state_op = MBWMClientWindowStateChangeAdd; + else if (e->data.l[0] == 2) + state_op = MBWMClientWindowStateChangeToggle; + + if (e->data.l[1] == wm->atoms[MBWM_ATOM_NET_WM_STATE_FULLSCREEN] + && ((c = mb_wm_managed_client_from_xwindow(wm, e->window)) != NULL) + && MB_WM_IS_CLIENT_APP (c)) + { + mb_wm_client_set_state (c, + MBWM_ATOM_NET_WM_STATE_FULLSCREEN, + state_op); + } + else if (e->data.l[1] == wm->atoms[MBWM_ATOM_NET_WM_STATE_ABOVE] + && ((c = mb_wm_managed_client_from_xwindow(wm, e->window)) != + NULL) + && MB_WM_IS_CLIENT_DIALOG (c)) + { + mb_wm_client_set_state (c, + MBWM_ATOM_NET_WM_STATE_ABOVE, + state_op); + } + return 1; + } + + else if (e->message_type == wm->atoms[MBWM_ATOM_WM_CHANGE_STATE]) + { + switch (e->data.l[0]) + { + case IconicState: + if ((c = mb_wm_managed_client_from_xwindow (wm, e->window))) + mb_wm_client_iconize (c); + + default: + MBWM_DBG ("Unhandled value %d for WM_CHANGE_STATE ClientMessage", + e->data.l[0]); + } + } + else if (e->message_type == wm->atoms[MBWM_ATOM_NET_SHOWING_DESKTOP]) + { + mb_wm_handle_show_desktop (wm, e->data.l[0]); + return 1; + } + else if (e->message_type == wm->atoms[MBWM_ATOM_NET_CURRENT_DESKTOP]) + { + mb_wm_select_desktop (wm, e->data.l[0]); + return 1; + } + else if (e->message_type == wm->atoms[MBWM_ATOM_MB_COMMAND]) + { + switch (e->data.l[0]) + { + case MB_CMD_EXIT: + exit(0); + case MB_CMD_NEXT: + mb_wm_cycle_apps (wm, False); + break; + case MB_CMD_PREV: + mb_wm_cycle_apps (wm, True); + break; + case MB_CMD_DESKTOP: + mb_wm_toggle_desktop (wm); + break; +#if ENABLE_COMPOSITE + case MB_CMD_COMPOSITE: + if (mb_wm_compositing_enabled (wm)) + mb_wm_compositing_off (wm); + else + mb_wm_compositing_on (wm); + break; +#endif + default: + /*FIXME -- not implemented yet */ + case MB_CMB_KEYS_RELOAD: + ; + } + } + + return 0; +} |