mirror of
https://github.com/gryf/wmaker.git
synced 2026-03-27 16:03:36 +01:00
Compare commits
8 Commits
6d6f9f6ff5
...
2fb9308a67
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2fb9308a67 | ||
|
|
d902477efd | ||
|
|
5ee19c2308 | ||
|
|
fabd4252ab | ||
|
|
630e9292c2 | ||
|
|
14d1b8197a | ||
|
|
4d658341d2 | ||
|
|
ac75047aef |
@@ -156,6 +156,7 @@ static const struct {
|
||||
{ "WindowRelaunchKey", N_("Launch new instance of application") },
|
||||
{ "ScreenSwitchKey", N_("Switch to Next Screen/Monitor") },
|
||||
{ "RunKey", N_("Run application") },
|
||||
{ "ExitKey", N_("Exit Window Maker") },
|
||||
{ "DockRaiseLowerKey", N_("Raise/Lower Dock") },
|
||||
{ "ClipRaiseLowerKey", N_("Raise/Lower Clip") }
|
||||
#ifdef XKB_MODELOCK
|
||||
|
||||
@@ -232,6 +232,7 @@
|
||||
WindowRelaunchKey = None;
|
||||
ScreenSwitchKey = None;
|
||||
RunKey = None;
|
||||
ExitKey = None;
|
||||
NormalCursor = (builtin, left_ptr);
|
||||
ArrowCursor = (builtin, top_left_arrow);
|
||||
MoveCursor = (builtin, fleur);
|
||||
|
||||
12
configure.ac
12
configure.ac
@@ -580,6 +580,18 @@ AS_IF([test "x$enable_wmreplace" = "xyes"],
|
||||
[define to support ICCCM protocol for window manager replacement])
|
||||
supported_xext="$supported_xext WMReplace"])
|
||||
|
||||
dnl XRes support
|
||||
dnl ==============
|
||||
m4_divert_push([INIT_PREPARE])dnl
|
||||
AC_ARG_ENABLE([res],
|
||||
[AS_HELP_STRING([--disable-res], [disable resource window extension support])],
|
||||
[AS_CASE(["$enableval"],
|
||||
[yes|no], [],
|
||||
[AC_MSG_ERROR([bad value $enableval for --enable-res]) ]) ],
|
||||
[enable_res=auto])
|
||||
m4_divert_pop([INIT_PREPARE])dnl
|
||||
|
||||
WM_XEXT_CHECK_XRES
|
||||
|
||||
dnl XShape support
|
||||
dnl ==============
|
||||
|
||||
@@ -16,6 +16,33 @@
|
||||
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
# WM_XEXT_CHECK_XRES
|
||||
# --------------------
|
||||
#
|
||||
# Check for the X Resource Window extension
|
||||
# The check depends on variable 'enable_xshape' being either:
|
||||
# yes - detect, fail if not found
|
||||
# no - do not detect, disable support
|
||||
# auto - detect, disable if not found
|
||||
#
|
||||
# When found, append appropriate stuff in XLIBS, and append info to
|
||||
# the variable 'supported_xext'
|
||||
# When not found, append info to variable 'unsupported'
|
||||
AC_DEFUN_ONCE([WM_XEXT_CHECK_XRES],
|
||||
[WM_LIB_CHECK([XRes], [-lXRes], [XResQueryClientIds], [$XLIBS],
|
||||
[wm_save_CFLAGS="$CFLAGS"
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([dnl
|
||||
@%:@include <X11/extensions/XRes.h>
|
||||
], [dnl
|
||||
|
||||
XResQueryClientIds(NULL, 0, NULL, NULL, NULL);])]
|
||||
[],
|
||||
[AC_MSG_ERROR([found $CACHEVAR but cannot compile using XRes header])])
|
||||
CFLAGS="$wm_save_CFLAGS"],
|
||||
[supported_xext], [XLIBS], [enable_res], [-])dnl
|
||||
]) dnl AC_DEFUN
|
||||
|
||||
|
||||
# WM_XEXT_CHECK_XSHAPE
|
||||
# --------------------
|
||||
#
|
||||
|
||||
@@ -912,6 +912,54 @@ void wUnmaximizeWindow(WWindow *wwin)
|
||||
WMPostNotificationName(WMNChangedState, wwin, "maximize");
|
||||
}
|
||||
|
||||
#ifdef USE_XINERAMA
|
||||
void wFullscreenMonitorsWindow(WWindow *wwin, unsigned long top, unsigned long bottom,
|
||||
unsigned long left, unsigned long right)
|
||||
{
|
||||
int i;
|
||||
long monitor;
|
||||
WMRect rect1, rect2;
|
||||
|
||||
if ((int)top < wwin->screen_ptr->xine_info.count &&
|
||||
(int)bottom < wwin->screen_ptr->xine_info.count &&
|
||||
(int)left < wwin->screen_ptr->xine_info.count &&
|
||||
(int)right < wwin->screen_ptr->xine_info.count) {
|
||||
wwin->flags.fullscreen_monitors[0] = top;
|
||||
wwin->flags.fullscreen_monitors[1] = bottom;
|
||||
wwin->flags.fullscreen_monitors[2] = left;
|
||||
wwin->flags.fullscreen_monitors[3] = right;
|
||||
} else {
|
||||
wwin->flags.fullscreen_monitors[0] = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
wwin->flags.fullscreen = True;
|
||||
wWindowConfigureBorders(wwin);
|
||||
ChangeStackingLevel(wwin->frame->core, WMFullscreenLevel);
|
||||
|
||||
wwin->bfs_geometry.x = wwin->frame_x;
|
||||
wwin->bfs_geometry.y = wwin->frame_y;
|
||||
wwin->bfs_geometry.width = wwin->frame->core->width;
|
||||
wwin->bfs_geometry.height = wwin->frame->core->height;
|
||||
|
||||
i = 0;
|
||||
monitor = wwin->flags.fullscreen_monitors[i];
|
||||
rect1 = wwin->screen_ptr->xine_info.screens[monitor];
|
||||
|
||||
for (i = 1; i <= 3; i++) {
|
||||
monitor = wwin->flags.fullscreen_monitors[i];
|
||||
rect2 = wwin->screen_ptr->xine_info.screens[monitor];
|
||||
wGetRectUnion(&rect1, &rect2, &rect1);
|
||||
}
|
||||
wWindowConfigure(wwin, rect1.pos.x, rect1.pos.y, rect1.size.width, rect1.size.height);
|
||||
|
||||
wwin->screen_ptr->bfs_focused_window = wwin->screen_ptr->focused_window;
|
||||
wSetFocusTo(wwin->screen_ptr, wwin);
|
||||
|
||||
WMPostNotificationName(WMNChangedState, wwin, "fullscreen");
|
||||
}
|
||||
#endif
|
||||
|
||||
void wFullscreenWindow(WWindow *wwin)
|
||||
{
|
||||
int head;
|
||||
|
||||
@@ -75,6 +75,9 @@ void wArrangeIcons(WScreen *scr, Bool arrangeAll);
|
||||
|
||||
void wMakeWindowVisible(WWindow *wwin);
|
||||
|
||||
void wFullscreenMonitorsWindow(WWindow *wwin, unsigned long top, unsigned long bottom,
|
||||
unsigned long left, unsigned long right);
|
||||
|
||||
void wFullscreenWindow(WWindow *wwin);
|
||||
void wUnfullscreenWindow(WWindow *wwin);
|
||||
|
||||
|
||||
@@ -788,6 +788,8 @@ WDefaultEntry optionList[] = {
|
||||
NULL, getKeybind, setKeyGrab, NULL, NULL},
|
||||
{"RunKey", "None", (void *)WKBD_RUN,
|
||||
NULL, getKeybind, setKeyGrab, NULL, NULL},
|
||||
{"ExitKey", "None", (void *)WKBD_EXIT,
|
||||
NULL, getKeybind, setKeyGrab, NULL, NULL},
|
||||
|
||||
#ifdef KEEP_XKB_LOCK_STATUS
|
||||
{"ToggleKbdModeKey", "None", (void *)WKBD_TOGGLE,
|
||||
|
||||
4
src/dialog.c
Executable file → Normal file
4
src/dialog.c
Executable file → Normal file
@@ -1433,6 +1433,10 @@ void wShowInfoPanel(WScreen *scr)
|
||||
strbuf = wstrappend(strbuf, ", XDnD");
|
||||
#endif
|
||||
|
||||
#ifdef USE_XRES
|
||||
strbuf = wstrappend(strbuf, ", XRes");
|
||||
#endif
|
||||
|
||||
#ifdef USE_MAGICK
|
||||
strbuf = wstrappend(strbuf, ", ImageMagick");
|
||||
#endif
|
||||
|
||||
21
src/event.c
21
src/event.c
@@ -1852,21 +1852,14 @@ static void handleKeyPress(XEvent * event)
|
||||
|
||||
case WKBD_RUN:
|
||||
{
|
||||
char *cmdline;
|
||||
ExecuteInputCommand(scr, _("exec %A(Run, Type command:)"));
|
||||
break;
|
||||
}
|
||||
|
||||
cmdline = ExpandOptions(scr, _("exec %A(Run,Type command to run:)"));
|
||||
|
||||
if (cmdline) {
|
||||
XGrabPointer(dpy, scr->root_win, True, 0,
|
||||
GrabModeAsync, GrabModeAsync, None, wPreferences.cursor[WCUR_WAIT], CurrentTime);
|
||||
XSync(dpy, False);
|
||||
|
||||
ExecuteShellCommand(scr, cmdline);
|
||||
wfree(cmdline);
|
||||
|
||||
XUngrabPointer(dpy, CurrentTime);
|
||||
XSync(dpy, False);
|
||||
}
|
||||
case WKBD_EXIT:
|
||||
{
|
||||
/* quick mode is not allowed to prevent inadvertently call */
|
||||
ExecuteExitCommand(scr, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -145,6 +145,9 @@ enum {
|
||||
/* open "run" dialog */
|
||||
WKBD_RUN,
|
||||
|
||||
/* open "exit" dialog */
|
||||
WKBD_EXIT,
|
||||
|
||||
#ifdef KEEP_XKB_LOCK_STATUS
|
||||
WKBD_TOGGLE,
|
||||
#endif
|
||||
|
||||
20
src/main.c
20
src/main.c
@@ -56,6 +56,7 @@
|
||||
#include "dialog.h"
|
||||
#include "main.h"
|
||||
#include "monitor.h"
|
||||
#include "misc.h"
|
||||
|
||||
#include <WINGs/WUtil.h>
|
||||
|
||||
@@ -354,11 +355,19 @@ Bool RelaunchWindow(WWindow *wwin)
|
||||
|
||||
char **argv;
|
||||
int argc;
|
||||
char *command = NULL;
|
||||
|
||||
if (! XGetCommand(dpy, wwin->client_win, &argv, &argc) || argc == 0 || argv == NULL) {
|
||||
command = GetCommandForWindow(wwin->client_win);
|
||||
if (!command) {
|
||||
#ifdef USE_XRES
|
||||
werror("cannot relaunch the application because no associated process found");
|
||||
#else
|
||||
werror("cannot relaunch the application because no WM_COMMAND property is set");
|
||||
#endif
|
||||
return False;
|
||||
}
|
||||
} else
|
||||
wtokensplit(command, &argv, &argc);
|
||||
|
||||
|
||||
pid_t pid = fork();
|
||||
|
||||
@@ -384,18 +393,19 @@ Bool RelaunchWindow(WWindow *wwin)
|
||||
} else if (pid < 0) {
|
||||
werror("cannot fork a new process");
|
||||
|
||||
XFreeStringList(argv);
|
||||
wfree(argv);
|
||||
wfree(command);
|
||||
return False;
|
||||
} else {
|
||||
_tuple *data = wmalloc(sizeof(_tuple));
|
||||
|
||||
data->scr = wwin->screen_ptr;
|
||||
data->command = wtokenjoin(argv, argc);
|
||||
data->command = command;
|
||||
|
||||
/* not actually a shell command */
|
||||
wAddDeathHandler(pid, shellCommandHandler, data);
|
||||
|
||||
XFreeStringList(argv);
|
||||
wfree(argv);
|
||||
}
|
||||
|
||||
return True;
|
||||
|
||||
59
src/misc.c
59
src/misc.c
@@ -53,6 +53,7 @@
|
||||
#include "xmodifier.h"
|
||||
#include "main.h"
|
||||
#include "event.h"
|
||||
#include "shutdown.h"
|
||||
|
||||
|
||||
#define ICON_SIZE wPreferences.icon_size
|
||||
@@ -679,6 +680,64 @@ char *ExpandOptions(WScreen *scr, const char *cmdline)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void ExecuteExitCommand(WScreen *scr, long quickmode)
|
||||
{
|
||||
static int inside = 0;
|
||||
int result;
|
||||
|
||||
/* prevent reentrant calls */
|
||||
if (inside)
|
||||
return;
|
||||
inside = 1;
|
||||
|
||||
#define R_CANCEL 0
|
||||
#define R_EXIT 1
|
||||
|
||||
result = R_CANCEL;
|
||||
|
||||
if (quickmode == M_QUICK) {
|
||||
result = R_EXIT;
|
||||
} else {
|
||||
int r, oldSaveSessionFlag;
|
||||
|
||||
oldSaveSessionFlag = wPreferences.save_session_on_exit;
|
||||
r = wExitDialog(scr, _("Exit"),
|
||||
_("Are you sure you want to quit Window Maker?"), _("Exit"), _("Cancel"), NULL);
|
||||
|
||||
if (r == WAPRDefault) {
|
||||
result = R_EXIT;
|
||||
} else if (r == WAPRAlternate) {
|
||||
/* Don't modify the "save session on exit" flag if the
|
||||
* user canceled the operation. */
|
||||
wPreferences.save_session_on_exit = oldSaveSessionFlag;
|
||||
}
|
||||
}
|
||||
if (result == R_EXIT)
|
||||
Shutdown(WSExitMode);
|
||||
|
||||
#undef R_EXIT
|
||||
#undef R_CANCEL
|
||||
inside = 0;
|
||||
}
|
||||
|
||||
void ExecuteInputCommand(WScreen *scr, const char *cmdline)
|
||||
{
|
||||
char *cmd;
|
||||
|
||||
cmd = ExpandOptions(scr, cmdline);
|
||||
if (cmd) {
|
||||
XGrabPointer(dpy, scr->root_win, True, 0,
|
||||
GrabModeAsync, GrabModeAsync, None, wPreferences.cursor[WCUR_WAIT], CurrentTime);
|
||||
XSync(dpy, False);
|
||||
|
||||
ExecuteShellCommand(scr, cmd);
|
||||
wfree(cmd);
|
||||
|
||||
XUngrabPointer(dpy, CurrentTime);
|
||||
XSync(dpy, False);
|
||||
}
|
||||
}
|
||||
|
||||
void ParseWindowName(WMPropList *value, char **winstance, char **wclass, const char *where)
|
||||
{
|
||||
char *name;
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
#include "keybind.h"
|
||||
#include "appicon.h"
|
||||
|
||||
#define M_QUICK 1
|
||||
|
||||
Bool wFetchName(Display *dpy, Window win, char **winname);
|
||||
Bool wGetIconName(Display *dpy, Window win, char **iconname);
|
||||
Bool UpdateDomainFile(WDDomain * domain);
|
||||
@@ -45,6 +47,8 @@ void SendHelperMessage(WScreen *scr, char type, int workspace, const char *msg);
|
||||
char *ShrinkString(WMFont *font, const char *string, int width);
|
||||
char *FindImage(const char *paths, const char *file);
|
||||
char *ExpandOptions(WScreen * scr, const char *cmdline);
|
||||
void ExecuteInputCommand(WScreen *scr, const char *cmdline);
|
||||
void ExecuteExitCommand(WScreen *scr, long quickmode);
|
||||
char *GetShortcutString(const char *text);
|
||||
char *GetShortcutKey(WShortKey key);
|
||||
char *EscapeWM_CLASS(const char *name, const char *class);
|
||||
|
||||
@@ -142,66 +142,17 @@ static Shortcut *shortcutList = NULL;
|
||||
*
|
||||
*/
|
||||
|
||||
#define M_QUICK 1
|
||||
|
||||
/* menu commands */
|
||||
|
||||
static void execCommand(WMenu * menu, WMenuEntry * entry)
|
||||
{
|
||||
char *cmdline;
|
||||
|
||||
cmdline = ExpandOptions(menu->frame->screen_ptr, (char *)entry->clientdata);
|
||||
|
||||
XGrabPointer(dpy, menu->frame->screen_ptr->root_win, True, 0,
|
||||
GrabModeAsync, GrabModeAsync, None, wPreferences.cursor[WCUR_WAIT], CurrentTime);
|
||||
XSync(dpy, 0);
|
||||
|
||||
if (cmdline) {
|
||||
ExecuteShellCommand(menu->frame->screen_ptr, cmdline);
|
||||
wfree(cmdline);
|
||||
}
|
||||
XUngrabPointer(dpy, CurrentTime);
|
||||
XSync(dpy, 0);
|
||||
ExecuteInputCommand(menu->frame->screen_ptr, (char *)entry->clientdata);
|
||||
}
|
||||
|
||||
static void exitCommand(WMenu * menu, WMenuEntry * entry)
|
||||
{
|
||||
static int inside = 0;
|
||||
int result;
|
||||
ExecuteExitCommand(menu->frame->screen_ptr, (long)entry->clientdata);
|
||||
|
||||
/* prevent reentrant calls */
|
||||
if (inside)
|
||||
return;
|
||||
inside = 1;
|
||||
|
||||
#define R_CANCEL 0
|
||||
#define R_EXIT 1
|
||||
|
||||
result = R_CANCEL;
|
||||
|
||||
if ((long)entry->clientdata == M_QUICK) {
|
||||
result = R_EXIT;
|
||||
} else {
|
||||
int r, oldSaveSessionFlag;
|
||||
|
||||
oldSaveSessionFlag = wPreferences.save_session_on_exit;
|
||||
r = wExitDialog(menu->frame->screen_ptr, _("Exit"),
|
||||
_("Are you sure you want to quit Window Maker?"), _("Exit"), _("Cancel"), NULL);
|
||||
|
||||
if (r == WAPRDefault) {
|
||||
result = R_EXIT;
|
||||
} else if (r == WAPRAlternate) {
|
||||
/* Don't modify the "save session on exit" flag if the
|
||||
* user canceled the operation. */
|
||||
wPreferences.save_session_on_exit = oldSaveSessionFlag;
|
||||
}
|
||||
}
|
||||
if (result == R_EXIT)
|
||||
Shutdown(WSExitMode);
|
||||
|
||||
#undef R_EXIT
|
||||
#undef R_CANCEL
|
||||
inside = 0;
|
||||
}
|
||||
|
||||
static void shutdownCommand(WMenu * menu, WMenuEntry * entry)
|
||||
|
||||
@@ -183,8 +183,13 @@ static WMPropList *makeWindowState(WWindow * wwin, WApplication * wapp)
|
||||
win = wwin->client_win;
|
||||
|
||||
command = GetCommandForWindow(win);
|
||||
if (!command)
|
||||
return NULL;
|
||||
if (!command) {
|
||||
if (wapp->app_icon && wapp->app_icon->command) {
|
||||
command = wmalloc(strlen(wapp->app_icon->command));
|
||||
strcpy(command, wapp->app_icon->command);
|
||||
} else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (PropGetWMClass(win, &class, &instance)) {
|
||||
if (class && instance)
|
||||
|
||||
43
src/window.c
43
src/window.c
@@ -29,6 +29,9 @@
|
||||
#ifdef KEEP_XKB_LOCK_STATUS
|
||||
#include <X11/XKBlib.h>
|
||||
#endif /* KEEP_XKB_LOCK_STATUS */
|
||||
#ifdef USE_XRES
|
||||
#include <X11/extensions/XRes.h>
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
@@ -475,6 +478,41 @@ Bool wWindowObscuresWindow(WWindow *wwin, WWindow *obscured)
|
||||
return True;
|
||||
}
|
||||
|
||||
/* Get the corresponding Process Identification Number of the active window */
|
||||
static pid_t getWindowPid(Window win)
|
||||
{
|
||||
pid_t pid = -1;
|
||||
|
||||
pid = wNETWMGetPidForWindow(win);
|
||||
#ifdef USE_XRES
|
||||
if (pid > 0)
|
||||
return pid;
|
||||
else {
|
||||
XResClientIdSpec spec;
|
||||
int status;
|
||||
long i, num_ids = 0;
|
||||
XResClientIdValue *client_ids = NULL;
|
||||
|
||||
spec.client = win;
|
||||
spec.mask = XRES_CLIENT_ID_PID_MASK;
|
||||
|
||||
status = XResQueryClientIds(dpy, 1, &spec, &num_ids, &client_ids);
|
||||
|
||||
if (status != Success)
|
||||
return -1;
|
||||
|
||||
for (i = 0; i < num_ids; i++) {
|
||||
if (client_ids[i].spec.mask == XRES_CLIENT_ID_PID_MASK) {
|
||||
pid = XResGetClientPid(&client_ids[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
XResClientIdsDestroy(num_ids, client_ids);
|
||||
}
|
||||
#endif
|
||||
return pid;
|
||||
}
|
||||
|
||||
static void fixLeaderProperties(WWindow *wwin)
|
||||
{
|
||||
XClassHint *classHint;
|
||||
@@ -487,7 +525,7 @@ static void fixLeaderProperties(WWindow *wwin)
|
||||
|
||||
classHint = XAllocClassHint();
|
||||
clientHints = XGetWMHints(dpy, wwin->client_win);
|
||||
pid = wNETWMGetPidForWindow(wwin->client_win);
|
||||
pid = getWindowPid(wwin->client_win);
|
||||
if (pid > 0)
|
||||
haveCommand = GetCommandForPid(pid, &argv, &argc);
|
||||
else
|
||||
@@ -688,6 +726,9 @@ WWindow *wManageWindow(WScreen *scr, Window window)
|
||||
XChangeWindowAttributes(dpy, window, CWEventMask | CWDontPropagate | CWSaveUnder, &attribs);
|
||||
XSetWindowBorderWidth(dpy, window, 0);
|
||||
|
||||
if (wwin->wm_class != NULL && strcmp(wwin->wm_class, "DockApp") != 0)
|
||||
wwin->flags.fullscreen_monitors[0] = -1;
|
||||
|
||||
/* get hints from GNUstep app */
|
||||
if (wwin->wm_class != NULL && strcmp(wwin->wm_class, "GNUstep") == 0)
|
||||
wwin->flags.is_gnustep = 1;
|
||||
|
||||
@@ -254,6 +254,7 @@ typedef struct WWindow {
|
||||
unsigned int maximized:7;
|
||||
unsigned int old_maximized:7;
|
||||
unsigned int fullscreen:1;
|
||||
long fullscreen_monitors[4];
|
||||
unsigned int omnipresent:1;
|
||||
unsigned int semi_focused:1;
|
||||
/* window type flags */
|
||||
|
||||
54
src/wmspec.c
54
src/wmspec.c
@@ -77,6 +77,9 @@ static Atom net_wm_visible_name; /* TODO (unnecessary?) */
|
||||
static Atom net_wm_icon_name;
|
||||
static Atom net_wm_visible_icon_name; /* TODO (unnecessary?) */
|
||||
static Atom net_wm_desktop;
|
||||
#ifdef USE_XINERAMA
|
||||
static Atom net_wm_fullscreen_monitors;
|
||||
#endif
|
||||
static Atom net_wm_window_type;
|
||||
static Atom net_wm_window_type_desktop;
|
||||
static Atom net_wm_window_type_dock;
|
||||
@@ -161,6 +164,9 @@ static atomitem_t atomNames[] = {
|
||||
{"_NET_WM_ICON_NAME", &net_wm_icon_name},
|
||||
{"_NET_WM_VISIBLE_ICON_NAME", &net_wm_visible_icon_name},
|
||||
{"_NET_WM_DESKTOP", &net_wm_desktop},
|
||||
#ifdef USE_XINERAMA
|
||||
{"_NET_WM_FULLSCREEN_MONITORS", &net_wm_fullscreen_monitors},
|
||||
#endif
|
||||
{"_NET_WM_WINDOW_TYPE", &net_wm_window_type},
|
||||
{"_NET_WM_WINDOW_TYPE_DESKTOP", &net_wm_window_type_desktop},
|
||||
{"_NET_WM_WINDOW_TYPE_DOCK", &net_wm_window_type_dock},
|
||||
@@ -287,6 +293,9 @@ static void setSupportedHints(WScreen *scr)
|
||||
atom[i++] = net_wm_moveresize;
|
||||
#endif
|
||||
atom[i++] = net_wm_desktop;
|
||||
#ifdef USE_XINERAMA
|
||||
atom[i++] = net_wm_fullscreen_monitors;
|
||||
#endif
|
||||
atom[i++] = net_wm_window_type;
|
||||
atom[i++] = net_wm_window_type_desktop;
|
||||
atom[i++] = net_wm_window_type_dock;
|
||||
@@ -1027,6 +1036,9 @@ static void updateStateHint(WWindow *wwin, Bool changedWorkspace, Bool del)
|
||||
{ /* changeable */
|
||||
if (del) {
|
||||
XDeleteProperty(dpy, wwin->client_win, net_wm_state);
|
||||
#ifdef USE_XINERAMA
|
||||
XDeleteProperty(dpy, wwin->client_win, net_wm_fullscreen_monitors);
|
||||
#endif
|
||||
} else {
|
||||
Atom state[15]; /* nr of defined state atoms */
|
||||
int i = 0;
|
||||
@@ -1067,6 +1079,20 @@ static void updateStateHint(WWindow *wwin, Bool changedWorkspace, Bool del)
|
||||
|
||||
XChangeProperty(dpy, wwin->client_win, net_wm_state, XA_ATOM, 32,
|
||||
PropModeReplace, (unsigned char *)state, i);
|
||||
|
||||
#ifdef USE_XINERAMA
|
||||
if (wwin->flags.fullscreen && (wwin->flags.fullscreen_monitors[0] != -1)) {
|
||||
unsigned long data[4];
|
||||
|
||||
data[0] = wwin->flags.fullscreen_monitors[0];
|
||||
data[1] = wwin->flags.fullscreen_monitors[1];
|
||||
data[2] = wwin->flags.fullscreen_monitors[2];
|
||||
data[3] = wwin->flags.fullscreen_monitors[3];
|
||||
|
||||
XChangeProperty(dpy, wwin->client_win, net_wm_fullscreen_monitors, XA_CARDINAL, 32,
|
||||
PropModeReplace, (unsigned char *)data, 4);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1260,8 +1286,10 @@ static void doStateAtom(WWindow *wwin, Atom state, int set, Bool init)
|
||||
} else {
|
||||
if (set)
|
||||
wFullscreenWindow(wwin);
|
||||
else
|
||||
else {
|
||||
wUnfullscreenWindow(wwin);
|
||||
wwin->flags.fullscreen_monitors[0] = -1;
|
||||
}
|
||||
}
|
||||
} else if (state == net_wm_state_above) {
|
||||
if (set == _NET_WM_STATE_TOGGLE)
|
||||
@@ -1759,8 +1787,30 @@ Bool wNETWMProcessClientMessage(XClientMessageEvent *event)
|
||||
wWindowChangeWorkspace(wwin, desktop);
|
||||
}
|
||||
return True;
|
||||
}
|
||||
|
||||
#ifdef USE_XINERAMA
|
||||
} else if (event->message_type == net_wm_fullscreen_monitors) {
|
||||
unsigned long top, bottom, left, right, src_indication;
|
||||
|
||||
top = event->data.l[0];
|
||||
bottom = event->data.l[1];
|
||||
left = event->data.l[2];
|
||||
right = event->data.l[3];
|
||||
src_indication = event->data.l[4];
|
||||
|
||||
if (src_indication > 1)
|
||||
wwarning("_NET_WM_FULLSCREEN_MONITORS source indication %ld not supported", src_indication);
|
||||
|
||||
wFullscreenMonitorsWindow(wwin, top, bottom, left, right);
|
||||
return True;
|
||||
}
|
||||
#else
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_WMSPEC
|
||||
wmessage("processClientMessage unsupported type %s", XGetAtomName(dpy, event->message_type));
|
||||
#endif
|
||||
return False;
|
||||
}
|
||||
|
||||
|
||||
12
src/wsmap.c
12
src/wsmap.c
@@ -337,9 +337,9 @@ static WMPixmap *get_mini_workspace(WWorkspaceMap *wsmap, int index)
|
||||
|
||||
static void create_mini_workspace(WScreen *scr, WWorkspaceMap *wsmap, W_WorkspaceMap *wsmap_array)
|
||||
{
|
||||
int workspace_index;
|
||||
unsigned short workspace_index;
|
||||
int mini_workspace_cnt;
|
||||
char name[10];
|
||||
char name[6];
|
||||
WMButton *mini_workspace_btn;
|
||||
WMPixmap *icon;
|
||||
|
||||
@@ -363,7 +363,7 @@ static void create_mini_workspace(WScreen *scr, WWorkspaceMap *wsmap, W_Workspac
|
||||
WMReleasePixmap(icon);
|
||||
}
|
||||
|
||||
snprintf(name, sizeof(name), "%d", workspace_index);
|
||||
snprintf(name, sizeof(name), "%hu", workspace_index);
|
||||
WMSetButtonText(mini_workspace_btn, name);
|
||||
WMSetButtonAction(mini_workspace_btn, selected_workspace_callback, wsmap);
|
||||
}
|
||||
@@ -423,9 +423,9 @@ static WWorkspaceMap *create_workspace_map(WScreen *scr, W_WorkspaceMap *wsmap_a
|
||||
|
||||
static void update_mini_workspace(WWorkspaceMap *wsmap, W_WorkspaceMap *wsmap_array, int bulk_of_ten)
|
||||
{
|
||||
int local_index, general_index;
|
||||
unsigned short local_index, general_index;
|
||||
int mini_workspace_cnt;
|
||||
char name[10];
|
||||
char name[6];
|
||||
WMPixmap *icon;
|
||||
|
||||
if (bulk_of_ten == wsmap_bulk_index)
|
||||
@@ -448,7 +448,7 @@ static void update_mini_workspace(WWorkspaceMap *wsmap, W_WorkspaceMap *wsmap_ar
|
||||
if (general_index < wsmap->scr->workspace_count) {
|
||||
/* updating label */
|
||||
WMSetLabelText(wsmap_array[local_index].workspace_label, wsmap->scr->workspaces[general_index]->name);
|
||||
snprintf(name, sizeof(name), "%d", general_index);
|
||||
snprintf(name, sizeof(name), "%hu", general_index);
|
||||
WMSetButtonText(wsmap_array[local_index].workspace_img_button, name);
|
||||
|
||||
/* updating label background*/
|
||||
|
||||
@@ -410,3 +410,33 @@ WMPoint wGetPointToCenterRectInHead(WScreen * scr, int head, int width, int heig
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
/* Find the bounding rect of the union of two rectangles */
|
||||
void wGetRectUnion(const WMRect *rect1, const WMRect *rect2, WMRect *dest)
|
||||
{
|
||||
int dest_x, dest_y;
|
||||
int dest_w, dest_h;
|
||||
|
||||
dest_x = rect1->pos.x;
|
||||
dest_y = rect1->pos.y;
|
||||
dest_w = rect1->size.width;
|
||||
dest_h = rect1->size.height;
|
||||
|
||||
if (rect2->pos.x < dest_x) {
|
||||
dest_w += dest_x - rect2->pos.x;
|
||||
dest_x = rect2->pos.x;
|
||||
}
|
||||
if (rect2->pos.y < dest_y) {
|
||||
dest_h += dest_y - rect2->pos.y;
|
||||
dest_y = rect2->pos.y;
|
||||
}
|
||||
if (rect2->pos.x + rect2->size.width > dest_x + dest_w)
|
||||
dest_w = rect2->pos.x + rect2->size.width - dest_x;
|
||||
if (rect2->pos.y + rect2->size.height > dest_y + dest_h)
|
||||
dest_h = rect2->pos.y + rect2->size.height - dest_y;
|
||||
|
||||
dest->pos.x = dest_x;
|
||||
dest->pos.y = dest_y;
|
||||
dest->size.width = dest_w;
|
||||
dest->size.height = dest_h;
|
||||
}
|
||||
|
||||
@@ -60,6 +60,8 @@ WArea wGetUsableAreaForHead(WScreen *scr, int head, WArea *totalAreaPtr, Bool no
|
||||
|
||||
WMPoint wGetPointToCenterRectInHead(WScreen *scr, int head, int width, int height);
|
||||
|
||||
void wGetRectUnion(const WMRect *rect1, const WMRect *rect2, WMRect *dest);
|
||||
|
||||
Bool wWindowTouchesHead(WWindow *wwin, int head);
|
||||
Bool wAppIconTouchesHead(WAppIcon *aicon, int head);
|
||||
|
||||
|
||||
@@ -95,19 +95,13 @@ static noreturn void my_error_exit(j_common_ptr cinfo)
|
||||
longjmp(myerr->setjmp_buffer, 1);
|
||||
}
|
||||
|
||||
RImage *RLoadJPEG(const char *file_name)
|
||||
static RImage *do_read_jpeg_file(struct jpeg_decompress_struct *cinfo, const char *file_name)
|
||||
{
|
||||
RImage *image = NULL;
|
||||
struct jpeg_decompress_struct cinfo;
|
||||
int i;
|
||||
unsigned char *ptr;
|
||||
JSAMPROW buffer[1], bptr;
|
||||
FILE *file;
|
||||
/* We use our private extension JPEG error handler.
|
||||
* Note that this struct must live as long as the main JPEG parameter
|
||||
* struct, to avoid dangling-pointer problems.
|
||||
*/
|
||||
struct my_error_mgr jerr;
|
||||
|
||||
file = fopen(file_name, "rb");
|
||||
if (!file) {
|
||||
@@ -115,6 +109,78 @@ RImage *RLoadJPEG(const char *file_name)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
jpeg_create_decompress(cinfo);
|
||||
jpeg_stdio_src(cinfo, file);
|
||||
jpeg_read_header(cinfo, TRUE);
|
||||
|
||||
if (cinfo->image_width < 1 || cinfo->image_height < 1) {
|
||||
buffer[0] = NULL; /* Initialize pointer to avoid spurious free in cleanup code */
|
||||
RErrorCode = RERR_BADIMAGEFILE;
|
||||
goto abort_and_release_resources;
|
||||
}
|
||||
|
||||
buffer[0] = (JSAMPROW) malloc(cinfo->image_width * cinfo->num_components);
|
||||
if (!buffer[0]) {
|
||||
RErrorCode = RERR_NOMEMORY;
|
||||
goto abort_and_release_resources;
|
||||
}
|
||||
|
||||
if (cinfo->jpeg_color_space == JCS_GRAYSCALE)
|
||||
cinfo->out_color_space = JCS_GRAYSCALE;
|
||||
else
|
||||
cinfo->out_color_space = JCS_RGB;
|
||||
|
||||
cinfo->quantize_colors = FALSE;
|
||||
cinfo->do_fancy_upsampling = FALSE;
|
||||
cinfo->do_block_smoothing = FALSE;
|
||||
jpeg_calc_output_dimensions(cinfo);
|
||||
image = RCreateImage(cinfo->image_width, cinfo->image_height, False);
|
||||
if (!image) {
|
||||
RErrorCode = RERR_NOMEMORY;
|
||||
goto abort_and_release_resources;
|
||||
}
|
||||
|
||||
jpeg_start_decompress(cinfo);
|
||||
ptr = image->data;
|
||||
if (cinfo->out_color_space == JCS_RGB) {
|
||||
while (cinfo->output_scanline < cinfo->output_height) {
|
||||
jpeg_read_scanlines(cinfo, buffer, (JDIMENSION) 1);
|
||||
bptr = buffer[0];
|
||||
memcpy(ptr, bptr, cinfo->image_width * 3);
|
||||
ptr += cinfo->image_width * 3;
|
||||
}
|
||||
} else {
|
||||
while (cinfo->output_scanline < cinfo->output_height) {
|
||||
jpeg_read_scanlines(cinfo, buffer, (JDIMENSION) 1);
|
||||
bptr = buffer[0];
|
||||
for (i = 0; i < cinfo->image_width; i++) {
|
||||
*ptr++ = *bptr;
|
||||
*ptr++ = *bptr;
|
||||
*ptr++ = *bptr++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
jpeg_finish_decompress(cinfo);
|
||||
|
||||
abort_and_release_resources:
|
||||
jpeg_destroy_decompress(cinfo);
|
||||
fclose(file);
|
||||
if (buffer[0])
|
||||
free(buffer[0]);
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
RImage *RLoadJPEG(const char *file_name)
|
||||
{
|
||||
struct jpeg_decompress_struct cinfo;
|
||||
/* We use our private extension JPEG error handler.
|
||||
* Note that this struct must live as long as the main
|
||||
* JPEG parameter struct, to avoid dangling-pointer problems.
|
||||
*/
|
||||
struct my_error_mgr jerr;
|
||||
|
||||
cinfo.err = jpeg_std_error(&jerr.pub);
|
||||
jerr.pub.error_exit = my_error_exit;
|
||||
/* Establish the setjmp return context for my_error_exit to use. */
|
||||
@@ -124,68 +190,7 @@ RImage *RLoadJPEG(const char *file_name)
|
||||
* We need to clean up the JPEG object, close the input file, and return.
|
||||
*/
|
||||
jpeg_destroy_decompress(&cinfo);
|
||||
fclose(file);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
jpeg_create_decompress(&cinfo);
|
||||
jpeg_stdio_src(&cinfo, file);
|
||||
jpeg_read_header(&cinfo, TRUE);
|
||||
if (cinfo.image_width < 1 || cinfo.image_height < 1) {
|
||||
buffer[0] = NULL; /* Initialize pointer to avoid spurious free in cleanup code */
|
||||
RErrorCode = RERR_BADIMAGEFILE;
|
||||
goto abort_and_release_resources;
|
||||
}
|
||||
|
||||
buffer[0] = (JSAMPROW) malloc(cinfo.image_width * cinfo.num_components);
|
||||
if (!buffer[0]) {
|
||||
RErrorCode = RERR_NOMEMORY;
|
||||
goto abort_and_release_resources;
|
||||
}
|
||||
|
||||
if (cinfo.jpeg_color_space == JCS_GRAYSCALE)
|
||||
cinfo.out_color_space = JCS_GRAYSCALE;
|
||||
else
|
||||
cinfo.out_color_space = JCS_RGB;
|
||||
|
||||
cinfo.quantize_colors = FALSE;
|
||||
cinfo.do_fancy_upsampling = FALSE;
|
||||
cinfo.do_block_smoothing = FALSE;
|
||||
jpeg_calc_output_dimensions(&cinfo);
|
||||
image = RCreateImage(cinfo.image_width, cinfo.image_height, False);
|
||||
if (!image) {
|
||||
RErrorCode = RERR_NOMEMORY;
|
||||
goto abort_and_release_resources;
|
||||
}
|
||||
|
||||
jpeg_start_decompress(&cinfo);
|
||||
ptr = image->data;
|
||||
if (cinfo.out_color_space == JCS_RGB) {
|
||||
while (cinfo.output_scanline < cinfo.output_height) {
|
||||
jpeg_read_scanlines(&cinfo, buffer, (JDIMENSION) 1);
|
||||
bptr = buffer[0];
|
||||
memcpy(ptr, bptr, cinfo.image_width * 3);
|
||||
ptr += cinfo.image_width * 3;
|
||||
}
|
||||
} else {
|
||||
while (cinfo.output_scanline < cinfo.output_height) {
|
||||
jpeg_read_scanlines(&cinfo, buffer, (JDIMENSION) 1);
|
||||
bptr = buffer[0];
|
||||
for (i = 0; i < cinfo.image_width; i++) {
|
||||
*ptr++ = *bptr;
|
||||
*ptr++ = *bptr;
|
||||
*ptr++ = *bptr++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
jpeg_finish_decompress(&cinfo);
|
||||
|
||||
abort_and_release_resources:
|
||||
jpeg_destroy_decompress(&cinfo);
|
||||
fclose(file);
|
||||
if (buffer[0])
|
||||
free(buffer[0]);
|
||||
|
||||
return image;
|
||||
return do_read_jpeg_file(&cinfo, file_name);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user