/* -*-c-*- */
/* Copyright (C) 2001 Olivier Chapuis */
/* 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 <stdio.h>
#include <X11/Xlib.h>
#include <X11/Xmd.h>
#include "libs/fvwmlib.h"
#include "libs/FScreen.h"
#include "libs/Strings.h"
#include "fvwm.h"
#include "execcontext.h"
#include "functions.h"
#include "misc.h"
#include "screen.h"
#include "virtual.h"
#include "commands.h"
#include "update.h"
#include "style.h"
#include "stack.h"
#include "events.h"
#include "ewmh.h"
#include "ewmh_intern.h"
#include "decorations.h"
#include "geometry.h"
#include "borders.h"
extern ewmh_atom ewmh_atom_wm_state[];
#define DEBUG_EWMH_INIT_STATE 0
/*
* root
*/
int ewmh_CurrentDesktop(EWMH_CMD_ARGS)
{
if (ev->xclient.data.l[0] < 0 || ev->xclient.data.l[0] > 0x7fffffff)
{
fvwm_msg(
WARN, "ewmh_CurrentDesktop",
"The application window (id %#lx)\n"
" \"%s\" tried to switch to an invalid desktop (%ld)\n"
" using an EWMH client message.\n"
" fvwm is ignoring this request.\n",
fw ? FW_W(fw) : 0, fw ? fw->name.name : "(none)",
ev->xclient.data.l[0]);
fvwm_msg_report_app_and_workers();
return -1;
}
goto_desk(ev->xclient.data.l[0]);
return -1;
}
int ewmh_DesktopGeometry(EWMH_CMD_ARGS)
{
char action[256];
long width = ev->xclient.data.l[0];
long height = ev->xclient.data.l[1];
width = width / Scr.MyDisplayWidth;
height = height / Scr.MyDisplayHeight;
if (width <= 0 || height <= 0)
{
fvwm_msg(
WARN, "ewmh_DesktopGeometry",
"The application window (id %#lx)\n"
" \"%s\" tried to set an invalid desktop geometry"
" (%ldx%ld)\n"
" using an EWMH client message.\n"
" fvwm is ignoring this request.\n",
fw ? FW_W(fw) : 0, fw ? fw->name.name : "(none)",
ev->xclient.data.l[0], ev->xclient.data.l[1]);
fvwm_msg_report_app_and_workers();
return -1;
}
sprintf(action, "DesktopSize %ld %ld", width, height);
execute_function_override_window(NULL, NULL, action, 0, NULL);
return -1;
}
int ewmh_DesktopViewPort(EWMH_CMD_ARGS)
{
if (
ev->xclient.data.l[0] < 0 ||
ev->xclient.data.l[0] > 0x7fffffff ||
ev->xclient.data.l[1] < 0 ||
ev->xclient.data.l[1] > 0x7fffffff)
{
fvwm_msg(
WARN, "ewmh_DesktopViewPort",
"The application window (id %#lx)\n"
" \"%s\" tried to switch to an invalid page"
" (%ldx%ld)\n"
" using an EWMH client message.\n"
" fvwm is ignoring this request.\n",
fw ? FW_W(fw) : 0, fw ? fw->name.name : "(none)",
ev->xclient.data.l[0], ev->xclient.data.l[1]);
fvwm_msg_report_app_and_workers();
return -1;
}
MoveViewport(ev->xclient.data.l[0], ev->xclient.data.l[1], 1);
return -1;
}
int ewmh_NumberOfDesktops(EWMH_CMD_ARGS)
{
int d = ev->xclient.data.l[0];
/* not a lot of sinification for fvwm */
if (d > 0 && (d <= ewmhc.MaxDesktops || ewmhc.MaxDesktops == 0))
{
ewmhc.NumberOfDesktops = d;
EWMH_SetNumberOfDesktops();
}
else
{
fvwm_msg(
WARN, "ewmh_NumberOfDesktops",
"The application window (id %#lx)\n"
" \"%s\" tried to set an invalid number of desktops"
" (%ld)\n"
" using an EWMH client message.\n"
" fvwm is ignoring this request.\n",
fw ? FW_W(fw) : 0, fw ? fw->name.name : "(none)",
ev->xclient.data.l[0]);
fvwm_msg_report_app_and_workers();
}
return -1;
}
/*
* window
*/
int ewmh_ActiveWindow(EWMH_CMD_ARGS)
{
if (ev == NULL)
{
return 0;
}
execute_function_override_window(
NULL, NULL, "EWMHActivateWindowFunc", 0, fw);
return 0;
}
int ewmh_CloseWindow(EWMH_CMD_ARGS)
{
if (ev == NULL)
{
return 0;
}
if (!is_function_allowed(F_CLOSE, NULL, fw, RQORIG_PROGRAM_US, False))
{
return 0;
}
execute_function_override_window(NULL, NULL, "Close", 0, fw);
return 0;
}
int ewmh_MoveResizeWindow(EWMH_CMD_ARGS)
{
XConfigureRequestEvent cre;
int func;
if (ev == NULL)
{
return 0;
}
if (
ev->xclient.data.l[3] == fw->g.normal.width &&
ev->xclient.data.l[4] == fw->g.normal.height)
{
func = F_MOVE;
}
else
{
func = F_RESIZE;
}
if (!is_function_allowed(func, NULL, fw, RQORIG_PROGRAM, False))
{
cre.value_mask = ev->xclient.data.l[0];
cre.x = ev->xclient.data.l[1];
cre.y = ev->xclient.data.l[2];
cre.width = ev->xclient.data.l[3];
cre.height = ev->xclient.data.l[4];
cre.window = ev->xclient.window;
events_handle_configure_request(cre, fw, True);
}
return 0;
}
int ewmh_RestackWindow(EWMH_CMD_ARGS)
{
XConfigureRequestEvent cre;
if (ev == NULL)
{
return 0;
}
if (DO_EWMH_USE_STACKING_HINTS(fw))
{
cre.value_mask = CWSibling | CWStackMode;
cre.above = ev->xclient.data.l[1];
cre.detail = ev->xclient.data.l[2];
cre.window = ev->xclient.window;
events_handle_configure_request(cre, fw, True);
}
return 0;
}
int ewmh_WMDesktop(EWMH_CMD_ARGS)
{
if (ev != NULL && style == NULL)
{
/* client message */
unsigned long d = (unsigned long)ev->xclient.data.l[0];
/* the spec says that if d = 0xFFFFFFFF then we have to Stick
* the window however KDE use 0xFFFFFFFE :o) */
if (d == (unsigned long)-2 || d == (unsigned long)-1)
{
execute_function_override_window(
NULL, NULL, "Stick on", 0, fw);
}
else if (d >= 0)
{
if (IS_STICKY_ACROSS_PAGES(fw) ||
IS_STICKY_ACROSS_DESKS(fw))
{
execute_function_override_window(
NULL, NULL, "Stick off", 0, fw);
}
if (fw->Desk != d)
{
do_move_window_to_desk(fw, (int)d);
}
}
else
{
fvwm_msg(
WARN, "ewmh_WMDesktop",
"The application window (id %#lx)\n"
" \"%s\" tried to move to an invalid desk"
" (%ld)\n"
" using an EWMH client message.\n"
" fvwm is ignoring this request.\n",
fw ? FW_W(fw) : 0, fw ? fw->name.name : "(none)",
ev->xclient.data.l[0]);
fvwm_msg_report_app_and_workers();
}
return 0;
}
if (style != NULL && ev == NULL)
{
/* start on desk */
unsigned long *val;
int size = 0;
if (DO_EWMH_IGNORE_STATE_HINTS(style))
{
SET_HAS_EWMH_INIT_WM_DESKTOP(
fw, EWMH_STATE_UNDEFINED_HINT);
return 0;
}
if (HAS_EWMH_INIT_WM_DESKTOP(fw) != EWMH_STATE_UNDEFINED_HINT)
{
return 0;
}
val = ewmh_AtomGetByName(
FW_W(fw), "_NET_WM_DESKTOP", EWMH_ATOM_LIST_CLIENT_WIN,
&size);
if (val == NULL)
{
SET_HAS_EWMH_INIT_WM_DESKTOP(fw, EWMH_STATE_NO_HINT);
return 0;
}
#if DEBUG_EWMH_INIT_STATE
fprintf(
stderr, "ewmh WM_DESKTOP hint for window 0x%lx "
"(%i,%lu,%lu)\n", FW_W(fw),
HAS_EWMH_INIT_WM_DESKTOP(fw),
fw->ewmh_hint_desktop, val[0]);
#endif
if (val[0] == (unsigned long)-2 || val[0] == (unsigned long)-1)
{
S_SET_IS_STICKY_ACROSS_PAGES(SCF(*style), 1);
S_SET_IS_STICKY_ACROSS_PAGES(SCM(*style), 1);
S_SET_IS_STICKY_ACROSS_PAGES(SCC(*style), 1);
S_SET_IS_STICKY_ACROSS_DESKS(SCF(*style), 1);
S_SET_IS_STICKY_ACROSS_DESKS(SCM(*style), 1);
S_SET_IS_STICKY_ACROSS_DESKS(SCC(*style), 1);
}
else if (val[0] < 256)
{
/* prevent crazy hints ?? */
style->flags.use_start_on_desk = 1;
style->flag_mask.use_start_on_desk = 1;
style->change_mask.use_start_on_desk = 1;
SSET_START_DESK(*style, val[0]);
}
SET_HAS_EWMH_INIT_WM_DESKTOP(fw, EWMH_STATE_HAS_HINT);
fw->ewmh_hint_desktop = val[0];
free(val);
}
return 0;
}
int ewmh_MoveResize(EWMH_CMD_ARGS)
{
int dir = -1;
int x_warp = 0;
int y_warp = 0;
Bool move = False;
char cmd[256];
if (ev == NULL)
{
return 0;
}
dir = ev->xclient.data.l[2];
switch(dir)
{
case _NET_WM_MOVERESIZE_SIZE_TOPLEFT:
break;
case _NET_WM_MOVERESIZE_SIZE_TOP:
x_warp = 50;
break;
case _NET_WM_MOVERESIZE_SIZE_TOPRIGHT:
x_warp = 100;
break;
case _NET_WM_MOVERESIZE_SIZE_RIGHT:
x_warp = 100; y_warp = 50;
break;
case _NET_WM_MOVERESIZE_SIZE_KEYBOARD:
case _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT:
x_warp = 100; y_warp = 100;
break;
case _NET_WM_MOVERESIZE_SIZE_BOTTOM:
x_warp = 50; y_warp = 100;
break;
case _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT:
y_warp = 100;
break;
case _NET_WM_MOVERESIZE_SIZE_LEFT:
y_warp = 50;
break;
case _NET_WM_MOVERESIZE_MOVE_KEYBOARD:
case _NET_WM_MOVERESIZE_MOVE:
move = True;
break;
default:
return 0;
}
if (move)
{
if (
!is_function_allowed(
F_MOVE, NULL, fw, RQORIG_PROGRAM_US, False))
{
return 0;
}
}
else
{
if (
!is_function_allowed(
F_RESIZE, NULL, fw, RQORIG_PROGRAM_US, False))
{
return 0;
}
}
if (!move)
{
sprintf(cmd, "WarpToWindow %i %i",x_warp,y_warp);
execute_function_override_window(NULL, NULL, cmd, 0, fw);
}
if (move)
{
execute_function_override_window(
NULL, NULL, "Move", 0, fw);
}
else
{
execute_function_override_window(
NULL, NULL, "Resize", 0, fw);
}
return 0;
}
/*
* WM_STATE*
*/
int ewmh_WMState(EWMH_CMD_ARGS)
{
unsigned long maximize = 0;
if (ev != NULL)
{
ewmh_atom *a1,*a2;
a1 = ewmh_GetEwmhAtomByAtom(
ev->xclient.data.l[1], EWMH_ATOM_LIST_WM_STATE);
a2 = ewmh_GetEwmhAtomByAtom(
ev->xclient.data.l[2], EWMH_ATOM_LIST_WM_STATE);
if (a1 != NULL)
{
maximize |= a1->action(fw, ev, NULL, 0);
}
if (a2 != NULL)
{
maximize |= a2->action(fw, ev, NULL, 0);
}
}
else if (style != NULL)
{
Atom *val;
int size = 0;
int i;
ewmh_atom *list = ewmh_atom_wm_state;
int has_hint = 0;
val = ewmh_AtomGetByName(
FW_W(fw), "_NET_WM_STATE", EWMH_ATOM_LIST_CLIENT_WIN,
&size);
if (val == NULL)
{
size = 0;
}
#if DEBUG_EWMH_INIT_STATE
if (size != 0)
{
fprintf(
stderr, "Window 0x%lx has an init"
" _NET_WM_STATE hint\n",FW_W(fw));
}
#endif
while(list->name != NULL)
{
has_hint = 0;
for(i = 0; i < (size / (sizeof(Atom))); i++)
{
if (list->atom == val[i])
{
has_hint = 1;
}
}
list->action(fw, NULL, style, has_hint);
list++;
}
if (val != NULL)
{
free(val);
}
return 0;
}
if (maximize != 0)
{
int max_vert = (maximize & EWMH_MAXIMIZE_VERT)? 100:0;
int max_horiz = (maximize & EWMH_MAXIMIZE_HORIZ)? 100:0;
char cmd[256];
if (maximize & EWMH_MAXIMIZE_REMOVE)
{
sprintf(cmd,"Maximize off");
}
else
{
if (!is_function_allowed(
F_MAXIMIZE, NULL, fw, RQORIG_PROGRAM_US,
False))
{
return 0;
}
sprintf(cmd,"Maximize on %i %i", max_horiz, max_vert);
}
execute_function_override_window(NULL, NULL, cmd, 0, fw);
}
return 0;
}
int ewmh_WMStateFullScreen(EWMH_CMD_ARGS)
{
if (ev == NULL && style == NULL)
{
return (IS_EWMH_FULLSCREEN(fw));
}
if (ev == NULL && style != NULL)
{
/* start full screen */
unsigned long has_hint = any;
#if DEBUG_EWMH_INIT_STATE
if (has_hint)
{
fprintf(stderr,"\tFullscreen\n");
}
#endif
if (DO_EWMH_IGNORE_STATE_HINTS(style))
{
SET_HAS_EWMH_INIT_FULLSCREEN_STATE(
fw, EWMH_STATE_UNDEFINED_HINT);
return 0;
}
if (HAS_EWMH_INIT_FULLSCREEN_STATE(fw) !=
EWMH_STATE_UNDEFINED_HINT)
{
return 0;
}
if (!has_hint)
{
SET_HAS_EWMH_INIT_FULLSCREEN_STATE(
fw, EWMH_STATE_NO_HINT);
return 0;
}
SET_EWMH_FULLSCREEN(fw,True);
SET_HAS_EWMH_INIT_FULLSCREEN_STATE(fw, EWMH_STATE_HAS_HINT);
return 0;
}
if (ev != NULL)
{
/* client message */
int bool_arg = ev->xclient.data.l[0];
int is_full_screen;
is_full_screen = IS_EWMH_FULLSCREEN(fw);
if ((bool_arg == NET_WM_STATE_TOGGLE && !is_full_screen) ||
bool_arg == NET_WM_STATE_ADD)
{
EWMH_fullscreen(fw);
}
else
{
if (HAS_EWMH_INIT_FULLSCREEN_STATE(fw) ==
EWMH_STATE_HAS_HINT)
{
/* the application started fullscreen */
SET_HAS_EWMH_INIT_FULLSCREEN_STATE(
fw, EWMH_STATE_NO_HINT);
}
/* unmaximize will restore is_ewmh_fullscreen,
* layer and apply_decor_change */
execute_function_override_window(
NULL, NULL, "Maximize off", 0, fw);
}
if ((IS_EWMH_FULLSCREEN(fw) &&
!DO_EWMH_USE_STACKING_HINTS(fw)) ||
(!IS_EWMH_FULLSCREEN(fw) &&
DO_EWMH_USE_STACKING_HINTS(fw)))
{
/* On: if not raised by a layer cmd raise
* Off: if lowered by a layer cmd raise */
execute_function_override_window(
NULL, NULL, "Raise", 0, fw);
}
}
return 0;
}
int ewmh_WMStateHidden(EWMH_CMD_ARGS)
{
if (ev == NULL && style == NULL)
{
unsigned long do_restore = any;
if (do_restore)
{
if (HAS_EWMH_INIT_HIDDEN_STATE(fw) ==
EWMH_STATE_HAS_HINT)
{
return True;
}
return False;
}
return IS_ICONIFIED(fw);
}
if (ev == NULL && style != NULL)
{
/* start iconified */
unsigned long has_hint = any;
#if DEBUG_EWMH_INIT_STATE
if (has_hint)
fprintf(stderr,"\tHidden\n");
#endif
if (DO_EWMH_IGNORE_STATE_HINTS(style))
{
SET_HAS_EWMH_INIT_HIDDEN_STATE(
fw, EWMH_STATE_UNDEFINED_HINT);
return 0;
}
if (HAS_EWMH_INIT_HIDDEN_STATE(fw) !=
EWMH_STATE_UNDEFINED_HINT)
{
return 0;
}
if (!has_hint)
{
SET_HAS_EWMH_INIT_HIDDEN_STATE(fw, EWMH_STATE_NO_HINT);
return 0;
}
style->flags.do_start_iconic = 1;
style->flag_mask.do_start_iconic = 1;
style->change_mask.do_start_iconic = 1;
SET_HAS_EWMH_INIT_HIDDEN_STATE(fw, EWMH_STATE_HAS_HINT);
return 0;
}
if (ev != NULL)
{
/* client message */
char cmd[16];
int bool_arg = ev->xclient.data.l[0];
if ((bool_arg == NET_WM_STATE_TOGGLE && !IS_ICONIFIED(fw)) ||
bool_arg == NET_WM_STATE_ADD)
{
/* iconify */
if (
!is_function_allowed(
F_ICONIFY, NULL, fw, RQORIG_PROGRAM_US,
False))
{
return 0;
}
sprintf(cmd, "Iconify on");
}
else
{
/* deiconify */
sprintf(cmd, "Iconify off");
}
execute_function_override_window(NULL, NULL, cmd, 0, fw);
}
return 0;
}
int ewmh_WMStateMaxHoriz(EWMH_CMD_ARGS)
{
if (ev == NULL && style == NULL)
{
#if 0
return (IS_MAXIMIZED(fw) && !IS_EWMH_FULLSCREEN(fw));
#else
/* DV: the notion of vertical/horizontal maximization does not
* make any sense in fvwm, so just claim we're never maximized
*/
return 0;
#endif
}
if (ev == NULL && style != NULL)
{
unsigned long has_hint = any;
#if DEBUG_EWMH_INIT_STATE
if (has_hint)
{
fprintf(
stderr, "\t Maxhoriz %i\n",
HAS_EWMH_INIT_MAXHORIZ_STATE(fw));
}
#endif
if (DO_EWMH_IGNORE_STATE_HINTS(style))
{
SET_HAS_EWMH_INIT_MAXHORIZ_STATE(
fw, EWMH_STATE_UNDEFINED_HINT);
return 0;
}
if (HAS_EWMH_INIT_MAXHORIZ_STATE(fw) !=
EWMH_STATE_UNDEFINED_HINT)
{
return 0;
}
if (!has_hint)
{
SET_HAS_EWMH_INIT_MAXHORIZ_STATE(
fw, EWMH_STATE_NO_HINT);
return 0;
}
SET_HAS_EWMH_INIT_MAXHORIZ_STATE(fw, EWMH_STATE_HAS_HINT);
return 0;
}
if (ev != NULL)
{
/* client message */
int bool_arg = ev->xclient.data.l[0];
if ((bool_arg == NET_WM_STATE_TOGGLE && !IS_MAXIMIZED(fw)) ||
bool_arg == NET_WM_STATE_ADD)
{
return EWMH_MAXIMIZE_HORIZ;
}
else
{
return EWMH_MAXIMIZE_REMOVE;
}
}
return 0;
}
int ewmh_WMStateMaxVert(EWMH_CMD_ARGS)
{
if (ev == NULL && style == NULL)
{
#if 0
return (IS_MAXIMIZED(fw) && !IS_EWMH_FULLSCREEN(fw));
#else
/* DV: the notion of vertical/horizontal maximization does not
* make any sense in fvwm, so just claim we're never maximized
*/
return 0;
#endif
}
if (ev == NULL && style != NULL)
{
unsigned long has_hint = any;
#if DEBUG_EWMH_INIT_STATE
if (has_hint)
{
fprintf(
stderr, "\t Maxvert %i\n",
HAS_EWMH_INIT_MAXVERT_STATE(fw));
}
#endif
if (DO_EWMH_IGNORE_STATE_HINTS(style))
{
SET_HAS_EWMH_INIT_MAXVERT_STATE(
fw, EWMH_STATE_UNDEFINED_HINT);
return 0;
}
if (HAS_EWMH_INIT_MAXVERT_STATE(fw) !=
EWMH_STATE_UNDEFINED_HINT)
{
return 0;
}
if (!has_hint)
{
SET_HAS_EWMH_INIT_MAXVERT_STATE(
fw, EWMH_STATE_NO_HINT);
return 0;
}
SET_HAS_EWMH_INIT_MAXVERT_STATE(fw, EWMH_STATE_HAS_HINT);
return 0;
}
if (ev != NULL)
{
/* client message */
int bool_arg = ev->xclient.data.l[0];
if ((bool_arg == NET_WM_STATE_TOGGLE && !IS_MAXIMIZED(fw)) ||
bool_arg == NET_WM_STATE_ADD)
{
return EWMH_MAXIMIZE_VERT;
}
else
{
return EWMH_MAXIMIZE_REMOVE;
}
}
return 0;
}
int ewmh_WMStateModal(EWMH_CMD_ARGS)
{
if (ev == NULL && style == NULL)
{
unsigned long do_restore = any;
if (do_restore)
{
if (HAS_EWMH_INIT_MODAL_STATE(fw) ==
EWMH_STATE_HAS_HINT)
{
return True;
}
return False;
}
return IS_EWMH_MODAL(fw);
}
if (ev == NULL && style != NULL)
{
unsigned long has_hint = any;
#if DEBUG_EWMH_INIT_STATE
if (has_hint)
{
fprintf(
stderr, "\t Modal %i\n",
HAS_EWMH_INIT_MODAL_STATE(fw));
}
#endif
if (DO_EWMH_IGNORE_STATE_HINTS(style))
{
SET_HAS_EWMH_INIT_MODAL_STATE(
fw, EWMH_STATE_UNDEFINED_HINT);
return 0;
}
if (HAS_EWMH_INIT_MODAL_STATE(fw) != EWMH_STATE_UNDEFINED_HINT)
{
return 0;
}
if (!has_hint)
{
SET_HAS_EWMH_INIT_MODAL_STATE(fw, EWMH_STATE_NO_HINT);
return 0;
}
/* the window map or had mapped with a modal hint */
if (IS_TRANSIENT(fw))
{
SET_EWMH_MODAL(fw, True);
/* the window is a modal transient window so we grab
* the focus it will be good to raise it but ... */
FPS_GRAB_FOCUS_TRANSIENT(
S_FOCUS_POLICY(SCF(*style)), 1);
FPS_GRAB_FOCUS_TRANSIENT(
S_FOCUS_POLICY(SCM(*style)), 1);
FPS_GRAB_FOCUS_TRANSIENT(
S_FOCUS_POLICY(SCC(*style)), 1);
SET_HAS_EWMH_INIT_MODAL_STATE(
fw, EWMH_STATE_HAS_HINT);
}
else
{
SET_EWMH_MODAL(fw, False);
if (!FP_DO_GRAB_FOCUS_TRANSIENT(
S_FOCUS_POLICY(SCF(*style))))
{
FPS_GRAB_FOCUS_TRANSIENT(
S_FOCUS_POLICY(SCF(*style)), 0);
FPS_GRAB_FOCUS_TRANSIENT(
S_FOCUS_POLICY(SCM(*style)), 1);
FPS_GRAB_FOCUS_TRANSIENT(
S_FOCUS_POLICY(SCC(*style)), 1);
}
}
return 0;
}
if (ev != NULL && fw != NULL)
{
/* client message: I do not think we can get such message */
int bool_arg = ev->xclient.data.l[0];
if ((bool_arg == NET_WM_STATE_TOGGLE &&
!IS_EWMH_MODAL(fw)) || bool_arg == NET_WM_STATE_ADD)
{
}
else
{
}
}
return 0;
}
int ewmh_WMStateShaded(EWMH_CMD_ARGS)
{
if (ev == NULL && style == NULL)
{
unsigned long do_restore = any;
if (do_restore)
{
if (HAS_EWMH_INIT_SHADED_STATE(fw) ==
EWMH_STATE_HAS_HINT)
{
return True;
}
return False;
}
return IS_SHADED(fw);
}
if (ev == NULL && style != NULL)
{
/* start shaded */
unsigned long has_hint = any;
#if DEBUG_EWMH_INIT_STATE
if (has_hint)
{
fprintf(
stderr, "\t Shaded %i\n",
HAS_EWMH_INIT_SHADED_STATE(fw));
}
#endif
if (DO_EWMH_IGNORE_STATE_HINTS(style))
{
SET_HAS_EWMH_INIT_SHADED_STATE(
fw, EWMH_STATE_UNDEFINED_HINT);
return 0;
}
if (HAS_EWMH_INIT_SHADED_STATE(fw) !=
EWMH_STATE_UNDEFINED_HINT)
{
return 0;
}
if (!has_hint)
{
SET_HAS_EWMH_INIT_SHADED_STATE(
fw, EWMH_STATE_NO_HINT);
return 0;
}
SET_SHADED(fw, 1);
SET_SHADED_DIR(fw, GET_TITLE_DIR(fw));
SET_HAS_EWMH_INIT_SHADED_STATE(fw, EWMH_STATE_HAS_HINT);
return 0;
}
if (ev != NULL)
{
/* client message */
int bool_arg = ev->xclient.data.l[0];
if ((bool_arg == NET_WM_STATE_TOGGLE && !IS_SHADED(fw)) ||
bool_arg == NET_WM_STATE_ADD)
{
execute_function_override_window(
NULL, NULL, "Windowshade on", 0, fw);
}
else
{
execute_function_override_window(
NULL, NULL, "Windowshade off", 0, fw);
}
}
return 0;
}
int ewmh_WMStateSkipPager(EWMH_CMD_ARGS)
{
if (ev == NULL && style == NULL)
{
unsigned long do_restore = any;
if (do_restore)
{
if (HAS_EWMH_INIT_SKIP_PAGER_STATE(fw) ==
EWMH_STATE_HAS_HINT)
{
return True;
}
return False;
}
return DO_SKIP_WINDOW_LIST(fw);
}
if (ev == NULL && style != NULL)
{
unsigned long has_hint = any;
#if DEBUG_EWMH_INIT_STATE
/*if (has_hint)*/
fprintf(
stderr, "\t Skip_Pager %lu, %i, %i\n", has_hint,
HAS_EWMH_INIT_SKIP_PAGER_STATE(fw),
DO_EWMH_IGNORE_STATE_HINTS(style));
#endif
if (DO_EWMH_IGNORE_STATE_HINTS(style))
{
SET_HAS_EWMH_INIT_SKIP_PAGER_STATE(
fw, EWMH_STATE_UNDEFINED_HINT);
return 0;
}
if (HAS_EWMH_INIT_SKIP_PAGER_STATE(fw) !=
EWMH_STATE_UNDEFINED_HINT)
{
return 0;
}
if (!has_hint)
{
SET_HAS_EWMH_INIT_SKIP_PAGER_STATE(
fw, EWMH_STATE_NO_HINT);
return 0;
}
S_SET_DO_WINDOW_LIST_SKIP(SCF(*style), 1);
S_SET_DO_WINDOW_LIST_SKIP(SCM(*style), 1);
S_SET_DO_WINDOW_LIST_SKIP(SCC(*style), 1);
SET_HAS_EWMH_INIT_SKIP_PAGER_STATE(fw, EWMH_STATE_HAS_HINT);
return 0;
}
if (ev != NULL)
{
/* I do not think we can get such client message */
int bool_arg = ev->xclient.data.l[0];
if ((bool_arg == NET_WM_STATE_TOGGLE &&
!DO_SKIP_WINDOW_LIST(fw)) ||
bool_arg == NET_WM_STATE_ADD)
{
}
else
{
}
}
return 0;
}
int ewmh_WMStateSkipTaskBar(EWMH_CMD_ARGS)
{
if (ev == NULL && style == NULL)
{
unsigned long do_restore = any;
if (do_restore)
{
if (HAS_EWMH_INIT_SKIP_TASKBAR_STATE(fw) ==
EWMH_STATE_HAS_HINT)
{
return True;
}
return False;
}
return DO_SKIP_WINDOW_LIST(fw);
}
if (ev == NULL && style != NULL)
{
unsigned long has_hint = any;
#if DEBUG_EWMH_INIT_STATE
/*if (has_hint)*/
fprintf(stderr,"\t Skip_Taskbar %lu, %i, %i\n",
has_hint,
HAS_EWMH_INIT_SKIP_TASKBAR_STATE(fw),
DO_EWMH_IGNORE_STATE_HINTS(style));
#endif
if (DO_EWMH_IGNORE_STATE_HINTS(style))
{
SET_HAS_EWMH_INIT_SKIP_TASKBAR_STATE(
fw, EWMH_STATE_UNDEFINED_HINT);
return 0;
}
if (HAS_EWMH_INIT_SKIP_TASKBAR_STATE(fw) !=
EWMH_STATE_UNDEFINED_HINT)
{
return 0;
}
if (!has_hint)
{
SET_HAS_EWMH_INIT_SKIP_TASKBAR_STATE(
fw, EWMH_STATE_NO_HINT);
return 0;
}
S_SET_DO_WINDOW_LIST_SKIP(SCF(*style), 1);
S_SET_DO_WINDOW_LIST_SKIP(SCM(*style), 1);
S_SET_DO_WINDOW_LIST_SKIP(SCC(*style), 1);
SET_HAS_EWMH_INIT_SKIP_TASKBAR_STATE(
fw, EWMH_STATE_HAS_HINT);
return 0;
}
if (ev != NULL)
{
/* I do not think we can get such client message */
int bool_arg = ev->xclient.data.l[0];
if ((bool_arg == NET_WM_STATE_TOGGLE &&
!DO_SKIP_WINDOW_LIST(fw)) ||
bool_arg == NET_WM_STATE_ADD)
{
}
else
{
}
}
return 0;
}
int ewmh_WMStateStaysOnTop(EWMH_CMD_ARGS)
{
if (ev == NULL && style == NULL)
{
unsigned long do_restore = any;
if (do_restore)
{
if (fw->ewmh_hint_layer == Scr.TopLayer)
{
return True;
}
return False;
}
if (fw->layer >= Scr.TopLayer)
{
return True;
}
return False;
}
if (ev == NULL && style != NULL)
{
unsigned long has_hint = any;
#if DEBUG_EWMH_INIT_STATE
if (has_hint)
{
fprintf(stderr,"\tStaysOnTop\n");
}
#endif
if (!DO_EWMH_USE_STACKING_HINTS(style))
{
return 0;
}
if (!has_hint && fw->ewmh_hint_layer == 0)
{
fw->ewmh_hint_layer = -1;
return 0;
}
if (fw->ewmh_hint_layer == -1)
{
return 0;
}
fw->ewmh_hint_layer = Scr.TopLayer;
SSET_LAYER(*style, Scr.TopLayer);
style->flags.use_layer = 1;
style->flag_mask.use_layer = 1;
style->change_mask.use_layer = 1;
return 0;
}
if (ev != NULL)
{
/* client message */
int bool_arg = ev->xclient.data.l[0];
if ((bool_arg == NET_WM_STATE_TOGGLE &&
fw->layer < Scr.TopLayer) ||
bool_arg == NET_WM_STATE_ADD)
{
new_layer(fw, Scr.TopLayer);
}
else
{
new_layer(fw, Scr.DefaultLayer);
}
}
return 0;
}
int ewmh_WMStateStaysOnBottom(EWMH_CMD_ARGS)
{
if (ev == NULL && style == NULL)
{
unsigned long do_restore = any;
if (do_restore)
{
if (fw->ewmh_hint_layer == Scr.BottomLayer)
{
return True;
}
return False;
}
if (fw->layer <= Scr.BottomLayer)
{
return True;
}
return False;
}
if (ev == NULL && style != NULL)
{
unsigned long has_hint = any;
#if DEBUG_EWMH_INIT_STATE
if (has_hint)
fprintf(stderr,"\tStaysOnBottom\n");
#endif
if (!DO_EWMH_USE_STACKING_HINTS(style))
{
return 0;
}
if (!has_hint && fw->ewmh_hint_layer == 0)
{
fw->ewmh_hint_layer = -1;
return 0;
}
if (fw->ewmh_hint_layer == -1)
{
return 0;
}
fw->ewmh_hint_layer = Scr.BottomLayer;
SSET_LAYER(*style, Scr.BottomLayer);
style->flags.use_layer = 1;
style->flag_mask.use_layer = 1;
style->change_mask.use_layer = 1;
return 0;
}
if (ev != NULL)
{
/* client message */
int bool_arg = ev->xclient.data.l[0];
if ((bool_arg == NET_WM_STATE_TOGGLE &&
fw->layer > Scr.BottomLayer) ||
bool_arg == NET_WM_STATE_ADD)
{
new_layer(fw, Scr.BottomLayer);
}
else
{
new_layer(fw, Scr.DefaultLayer);
}
}
return 0;
}
int ewmh_WMStateSticky(EWMH_CMD_ARGS)
{
if (ev == NULL && style == NULL)
{
unsigned long do_restore = any;
if (do_restore)
{
if (HAS_EWMH_INIT_STICKY_STATE(fw) ==
EWMH_STATE_HAS_HINT)
{
return True;
}
return False;
}
return (IS_STICKY_ACROSS_PAGES(fw) &&
IS_STICKY_ACROSS_DESKS(fw));
}
if (ev == NULL && style != NULL)
{
/* start sticky */
unsigned long has_hint = any;
#if DEBUG_EWMH_INIT_STATE
if (has_hint)
{
fprintf(stderr,"\t Sticky\n");
}
#endif
if (DO_EWMH_IGNORE_STATE_HINTS(style))
{
SET_HAS_EWMH_INIT_STICKY_STATE(
fw, EWMH_STATE_UNDEFINED_HINT);
return 0;
}
if (HAS_EWMH_INIT_STICKY_STATE(fw) !=
EWMH_STATE_UNDEFINED_HINT)
{
return 0;
}
if (!has_hint)
{
SET_HAS_EWMH_INIT_STICKY_STATE(
fw, EWMH_STATE_NO_HINT);
return 0;
}
S_SET_IS_STICKY_ACROSS_PAGES(SCF(*style), 1);
S_SET_IS_STICKY_ACROSS_PAGES(SCM(*style), 1);
S_SET_IS_STICKY_ACROSS_PAGES(SCC(*style), 1);
S_SET_IS_STICKY_ACROSS_DESKS(SCF(*style), 1);
S_SET_IS_STICKY_ACROSS_DESKS(SCM(*style), 1);
S_SET_IS_STICKY_ACROSS_DESKS(SCC(*style), 1);
SET_HAS_EWMH_INIT_STICKY_STATE(fw, EWMH_STATE_HAS_HINT);
return 0;
}
if (ev != NULL)
{
/* client message */
int bool_arg = ev->xclient.data.l[0];
if ((bool_arg == NET_WM_STATE_TOGGLE &&
(!IS_STICKY_ACROSS_PAGES(fw) ||
!IS_STICKY_ACROSS_DESKS(fw))) ||
bool_arg == NET_WM_STATE_ADD)
{
execute_function_override_window(
NULL, NULL, "Stick on", 0, fw);
}
else
{
execute_function_override_window(
NULL, NULL, "Stick on", 1, fw);
}
}
return 0;
}
/*
* Property Notify (_NET_WM_ICON is in ewmh_icon.c, _NET_WM_*NAME are in
* ewmh_name) *
*/
int ewmh_WMIconGeometry(EWMH_CMD_ARGS)
{
int size;
CARD32 *val;
/* FIXME: After a (un)slide of kicker the geometry are wrong (not
* because we set the geometry just after the property notify). This
* does not happen with kwin */
val = ewmh_AtomGetByName(
FW_W(fw), "_NET_WM_ICON_GEOMETRY",
EWMH_ATOM_LIST_PROPERTY_NOTIFY, &size);
if (val != NULL && size < 4 * sizeof(CARD32))
{
fvwm_msg(
WARN, "ewmh_WMIconGeometry",
"The application window (id %#lx)\n"
" \"%s\" tried to set to an icon geometry via EWMH\n"
" but provided only %d of the 4 values required.\n"
" fvwm is ignoring this request.\n",
fw ? FW_W(fw) : 0, fw ? fw->name.name : "(none)",
(int)(size / sizeof(CARD32)));
fvwm_msg_report_app_and_workers();
free(val);
val = NULL;
}
if (val == NULL)
{
fw->ewmh_icon_geometry.x = 0;
fw->ewmh_icon_geometry.y = 0;
fw->ewmh_icon_geometry.width = 0;
fw->ewmh_icon_geometry.height = 0;
return 0;
}
fw->ewmh_icon_geometry.x = val[0];
fw->ewmh_icon_geometry.y = val[1];
fw->ewmh_icon_geometry.width = val[2];
fw->ewmh_icon_geometry.height = val[3];
free(val);
return 0;
}
/**** for animation ****/
void EWMH_GetIconGeometry(FvwmWindow *fw, rectangle *icon_rect)
{
if (!IS_ICON_SUPPRESSED(fw) ||
(fw->ewmh_icon_geometry.x == 0 &&
fw->ewmh_icon_geometry.y == 0 &&
fw->ewmh_icon_geometry.width == 0 &&
fw->ewmh_icon_geometry.height == 0))
{
return;
}
icon_rect->x = fw->ewmh_icon_geometry.x;
icon_rect->y = fw->ewmh_icon_geometry.y;
icon_rect->width = fw->ewmh_icon_geometry.width;
icon_rect->height = fw->ewmh_icon_geometry.height;
return;
}
int ewmh_WMStrut(EWMH_CMD_ARGS)
{
int size = 0;
CARD32 *val;
if (ev == NULL)
{
fw->dyn_strut.left = fw->strut.left = 0;
fw->dyn_strut.right = fw->strut.right = 0;
fw->dyn_strut.top = fw->strut.top = 0;
fw->dyn_strut.bottom = fw->strut.bottom = 0;
}
val = ewmh_AtomGetByName(
FW_W(fw), "_NET_WM_STRUT",
EWMH_ATOM_LIST_PROPERTY_NOTIFY, &size);
if (val == NULL)
{
return 0;
}
if ((val[0] > 0 || val[1] > 0 || val[2] > 0 || val[3] > 0)
&&
(val[0] != fw->strut.left || val[1] != fw->strut.right ||
val[2] != fw->strut.top || val[3] != fw->strut.bottom))
{
fw->strut.left = val[0];
fw->strut.right = val[1];
fw->strut.top = val[2];
fw->strut.bottom = val[3];
ewmh_ComputeAndSetWorkArea();
}
if (val[0] != fw->dyn_strut.left ||
val[1] != fw->dyn_strut.right ||
val[2] != fw->dyn_strut.top ||
val[3] != fw->dyn_strut.bottom)
{
fw->dyn_strut.left = val[0];
fw->dyn_strut.right = val[1];
fw->dyn_strut.top = val[2];
fw->dyn_strut.bottom = val[3];
ewmh_HandleDynamicWorkArea();
}
free(val);
return 0;
}
Bool EWMH_ProcessClientMessage(const exec_context_t *exc)
{
ewmh_atom *ewmh_a = NULL;
FvwmWindow *fw = exc->w.fw;
XEvent *ev = exc->x.elast;
if ((ewmh_a = (ewmh_atom *)ewmh_GetEwmhAtomByAtom(
ev->xclient.message_type, EWMH_ATOM_LIST_CLIENT_ROOT)) !=
NULL)
{
if (ewmh_a->action != None)
{
ewmh_a->action(fw, ev, NULL, 0);
}
return True;
}
if ((ewmh_a = (ewmh_atom *)ewmh_GetEwmhAtomByAtom(
ev->xclient.message_type, EWMH_ATOM_LIST_CLIENT_WIN))
== NULL)
{
return False;
}
if (ev->xclient.window == None)
{
return False;
}
/* these one are special: we can get it on an unamaged window */
if (StrEquals(ewmh_a->name, "_NET_MOVERESIZE_WINDOW") ||
StrEquals(ewmh_a->name, "_NET_RESTACK_WINDOW"))
{
ewmh_a->action(fw, ev, NULL, 0);
return True;
}
if (fw == NULL)
{
return False;
}
if ((ewmh_a = (ewmh_atom *)ewmh_GetEwmhAtomByAtom(
ev->xclient.message_type, EWMH_ATOM_LIST_CLIENT_WIN)) !=
NULL)
{
if (ewmh_a->action != None)
{
ewmh_a->action(fw, ev, NULL, 0);
}
return True;
}
return False;
}
void EWMH_ProcessPropertyNotify(const exec_context_t *exc)
{
ewmh_atom *ewmh_a = NULL;
FvwmWindow *fw = exc->w.fw;
XEvent *ev = exc->x.elast;
if ((ewmh_a = (ewmh_atom *)ewmh_GetEwmhAtomByAtom(
ev->xproperty.atom, EWMH_ATOM_LIST_PROPERTY_NOTIFY)) !=
NULL)
{
if (ewmh_a->action != None)
{
flush_property_notify(ewmh_a->atom, FW_W(fw));
ewmh_a->action(fw, ev, NULL, 0);
}
}
}
syntax highlighted by Code2HTML, v. 0.9.1