1
0
mirror of https://github.com/gryf/wmaker.git synced 2026-04-05 06:43:33 +02:00

22 Commits

Author SHA1 Message Date
David Maciejak
2fb9308a67 Info Panel: Add libXRes info if supported
If windowmaker was compiled with libXRes,
add XRes info in the "Additional support" section.

Take also the chance to remove the mode +x on the source code file.
2023-02-20 23:07:02 +00:00
David Maciejak
d902477efd Set missing WM_COMMAND using pid given from libXRes
For apps which are not setting the window WM_COMMAND property like those old
apps using Motif toolkit (I am thinking of NEdit for example)
it's bringing some issues in windowmaker which is relying on it for a few interactions.
Especially,
*an app without WM_COMMAND will not be saved during the workspace state
(so session restore is not working for them)
*when added to the dock, the settings parameters are empty and need to be filled
*cannot autostart from the dock (even if the settings are manually filled and saved)
*right click on the app titlebar, and choosing Launch has no effect

Most of the time, those apps are also not setting the X11_NET_WM_PID property.
With the pid we could have a chance to find the running program.
To link a window to a pid, there is the X11 Resource extension library (libXRes).
After checking, gnome and xfce are also using the same method to handle such issues.

The patch is checking if the libXRes is present on the system (but it's not mandatory to compile).
Then, it adds a layer on top of wNETWMGetPidForWindow to not only check the window property
but if necessary to get the underlying pid from libXRes if available.
That's solving the points mentioned above.
2023-02-20 15:00:55 +00:00
David Maciejak
5ee19c2308 Allow WM_COMMAND-less app to autostart
For apps which are not setting the window WM_COMMAND property like those old
apps using Motif toolkit (I am thinking of NEdit for example)
it's bringing some issues in windowmaker which is relying on it for a few interactions.
Especially,
*an app without WM_COMMAND will not be saved during the workspace state
(so session restore is not working for them)
*when added to the dock, the settings parameters are empty and need to be filled
*cannot autostart from the dock (even if the settings are manually filled and saved)
*right click on the app titlebar, and choosing Launch has no effect

The patch below allows the workspace state to be saved for those apps without WM_COMMAND
that have been launched from the dock. We are just reusing what have been set in the
Application Path Settings of the dock app (and it does not require extra libs like libXRes).
2023-02-20 15:00:55 +00:00
David Maciejak
fabd4252ab Allow exit panel to be bound to a key shortcut
While debugging the save/restore workspace state, I found quite
useful to be able to exit windowmaker using a key shortcut.
2023-02-20 15:00:55 +00:00
David Maciejak
630e9292c2 Factorize duplicate run command code
Run command from the menu and run command from the key shortcut are from two different codes.
Merge them into one function instead.
2023-02-19 10:10:49 +00:00
David Maciejak
14d1b8197a WRaster: Avoid undefined setjmp() behavior with libjpeg
Fix compiler warning:
load_jpeg.c: In function 'RLoadJPEG':
load_jpeg.c:100:17: warning: variable 'image' might be clobbered by 'longjmp' or 'vfork' [-Wclobbered]

As it was not working to only set the RImage *image as volatile,
I had to refactor the code by following the example from
410c028f33 (diff-e7cb632359a2be17c1008b50f9ec85691cd5d66834d5fe8f63ef65ceb06682ee)
2023-02-19 10:10:41 +00:00
David Maciejak
4d658341d2 Add support for _NET_WM_FULLSCREEN_MONITORS
This patch adds the _NET_WM_FULLSCREEN_MONITORS hint as defined in EWMH which is based on Xinerama.
It's allowing a window to be displayed fullscreen on multiple monitors.

Issue mentioned at https://github.com/window-maker/wmaker/issues/8
Specs at https://specifications.freedesktop.org/wm-spec/1.5/ar01s06.html#idm45763309187776
GTK test program used https://bugzilla.gnome.org/show_bug.cgi?id=414476
2023-02-18 08:41:08 +00:00
David Maciejak
ac75047aef Fix mini workspace compiler warnings
The patch is to fix warnings like:
wsmap.c: In function "update_mini_workspace":
wsmap.c:451:55: warning: "%d" directive output may be truncated writing between 1 and 11 bytes into a region of size 10 [-Wformat-truncation=]
  451 |                         snprintf(name, sizeof(name), "%d", general_index);
2023-02-17 21:51:06 +00:00
David Maciejak
6d6f9f6ff5 Info Panel: Fix uninitialized posn variable 2023-02-16 11:34:54 +00:00
David Maciejak
370adc94e7 Ignore WM_NORMAL_HINTS resize increment for maximized windows
If you are trying to maximize old apps that are setting a resize increment
in term of WM_NORMAL_HINTS notion the window will not be maximized fully (by a few pixels).
It's easy to reproduce with xterm, ctrl double click on the title bar.
xprop extract sample is giving:
program specified resize increment: 6 by 13

For those maximized windows the patch is just ignoring the resize increment.
Seems the same issue happened on that project
https://github.com/paperwm/PaperWM/issues/106
2023-02-16 01:21:25 +00:00
David Maciejak
532acdc443 WRaster: Avoid types deprecated with libtiff 4.3
This patch is fixing compiler warnings like:

load_tiff.c:42:9: warning: 'uint16' is deprecated [-Wdeprecated-declarations]
load_tiff.c:43:9: warning: 'uint32' is deprecated [-Wdeprecated-declarations]

As starting from libtiff 4.3, released in April 2021, types were moved
from uint16 to uint16_t and uint32 to uint32_t respectively.

See https://libtiff.gitlab.io/libtiff/releases/v4.3.0.html
2023-02-15 11:24:09 +00:00
David Maciejak
d7d38aa443 Info Panel: display more OS details
Rely on old utsname and os-release (http://0pointer.de/blog/projects/os-release) when available
to display more underlying OS details in the Info panel.
The idea is when someone creates a bug entry we can request them to copy/paste that screen
to give more info about the context that could help us debug the issue.
For example, on my current system it's displaying:
"Running on: Ubuntu 22.10 (x86_64)"
2023-02-15 09:37:06 +00:00
David Maciejak
a6209cc89b Set a better exit panel message
Replace the exit window manager generic message with Window Maker term instead.
2023-02-15 09:37:06 +00:00
David Maciejak
01bd523cee WINGs: allow keypad enter key to validate button
This patch allows the keypad enter key to validate the button click action.
2023-02-15 09:37:06 +00:00
David Maciejak
45ab72a78a InfoPanel: fix out of display text
When debug is enabled, the memory allocated details is supposed to display the free chunks
but as the text length is too long it's getting out of the display area.
This patch is increasing the window width to handle such case.
2023-02-13 13:10:14 +00:00
David Maciejak
437b76812d Info Panel: mallinfo is deprecated use mallinfo2 instead
Replacing mallinfo with mallinfo2.

The fields of the mallinfo structure that is returned by the
older mallinfo() function are typed as int.  However, because
some internal bookkeeping values may be of type long, the
reported values may wrap around zero and thus be inaccurate.
2023-02-11 10:35:23 +00:00
David Maciejak
e3ee459a78 Info Panel: use system time to get the current year
Use the system date to get the current year to insert inside the copyright line.
So no need to update that string anymore.
2023-02-11 10:33:22 +00:00
David Maciejak
d70b546f2e Fix wrong XKeycodeToKeysym index value
XKeycodeToKeysym was deprecated some time ago and wmaker code was patched to use the definition from XKBlib instead.
(https://repo.or.cz/wmaker-crm.git?a=commit;h=0382dd5dd7ecae2112a0c6366eaf9e6ab68ad354)

Before being deprecated,  XKeycodeToKeysym was prototyped at X11/Xlib.h as
KeySym XKeycodeToKeysym(display, keycode, index)

Now it's available in X11/XKBlib.h as
KeySym XkbKeycodeToKeysym(display, keycode, group, level)

Basically level now which is the 4th parameter is our old index variable (3rd parameter).

On systems which don't have xkb supported the value set for index is wrong.
As seen in old patch at https://repo.or.cz/wmaker-crm.git/blobdiff/139f912e618870cc7fd908099f203450547eb658..43c3526d2120712f72579398b73ef92283d9078b:/WPrefs.app/MouseSettings.c
we should pass the l value to old XKeycodeToKeysym function and not the 0 value which is used for the group in the new XkbKeycodeToKeysym definition.
2023-02-11 10:30:52 +00:00
David Maciejak
812930b7cd Fix icon.c unused variable compiler warning
Just to please the compiler as it's reporting:
icon.c: In function 'get_icon_cache_path':
icon.c:425:13: warning: unused variable 'len' [-Wunused-variable]
2023-02-11 10:30:02 +00:00
David Maciejak
2a14004fc3 SwitchPanel: make sure WMRetainColor and WMReleaseColor calls are even
The number of calls to WMRetainColor for a color in use should the same as the number of calls to WMReleaseColor
to free that color. In case of discrepancy, random crashes can happen and memory is not freed properly.
To debug that issue I checked the retained colors when the switchpanel is opened and then checked if those colors are properly released once the panel is closed.

This patch fixes the issue mentioned at https://github.com/window-maker/wmaker/issues/22
2023-02-10 11:24:55 +00:00
David Maciejak
04e9f33437 WINGs: Fix incorrect findCloseColor exact flag value
In case the color cannot be allocated exactly by createRGBAColor function,
the findCloseColor function is used as a failover function to find a color close to the requested color.
By definition that color is then not exact.
createRGBAColor exact flag should be 1 while findCloseColor exact flag should be 0
2023-02-10 11:24:44 +00:00
David Maciejak
150816c687 Fix missing linefeed on the error message
Just to display the error message properly in case there is no display.
2023-02-08 00:14:48 +00:00
30 changed files with 548 additions and 193 deletions

View File

@@ -51,7 +51,7 @@ static WMColor *findCloseColor(WMScreen * scr, unsigned short red, unsigned shor
color->refCount = 1;
color->color = xcolor;
color->alpha = alpha;
color->flags.exact = 1;
color->flags.exact = 0;
color->gc = NULL;
return color;
@@ -91,7 +91,7 @@ WMColor *WMCreateRGBColor(WMScreen * scr, unsigned short red, unsigned short gre
color = findCloseColor(scr, red, green, blue, 0xffff);
}
if (!color)
color = WMBlackColor(scr);
color = scr->black;
return color;
}
@@ -117,7 +117,7 @@ WMColor *WMCreateRGBAColor(WMScreen * scr, unsigned short red, unsigned short gr
color = findCloseColor(scr, red, green, blue, alpha);
}
if (!color)
color = WMBlackColor(scr);
color = scr->black;
return color;
}

View File

@@ -253,6 +253,9 @@ WMFrame *WMCreateFrame(WMWidget * parent)
static void destroyFrame(Frame * fPtr)
{
if (fPtr->textColor)
WMReleaseColor(fPtr->textColor);
if (fPtr->caption)
wfree(fPtr->caption);

View File

@@ -25,7 +25,7 @@ static void handleKeyPress(XEvent * event, void *clientData)
XLookupString(&event->xkey, NULL, 0, &ksym, NULL);
if (ksym == XK_Return && panel->defBtn) {
if ((ksym == XK_Return || ksym == XK_KP_Enter) && panel->defBtn) {
WMPerformButtonClick(panel->defBtn);
} else if (ksym == XK_Escape) {
if (panel->altBtn || panel->othBtn) {
@@ -421,7 +421,7 @@ static void handleKeyPress2(XEvent * event, void *clientData)
XLookupString(&event->xkey, NULL, 0, &ksym, NULL);
if (ksym == XK_Return && panel->defBtn) {
if ((ksym == XK_Return || ksym == XK_KP_Enter) && panel->defBtn) {
WMPerformButtonClick(panel->defBtn);
} else if (ksym == XK_Escape) {
if (panel->altBtn) {
@@ -709,7 +709,7 @@ static void handleKeyPress3(XEvent * event, void *clientData)
XLookupString(&event->xkey, NULL, 0, &ksym, NULL);
if (ksym == XK_Return && panel->defBtn) {
if ((ksym == XK_Return || ksym == XK_KP_Enter) && panel->defBtn) {
WMPerformButtonClick(panel->defBtn);
} else if (ksym == XK_Escape) {
if (panel->altBtn) {

View File

@@ -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
@@ -320,7 +321,7 @@ char *capture_shortcut(Display *dpy, Bool *capturing, Bool convert_case)
/* conditional mask check to get numeric keypad keys */
ksym = XkbKeycodeToKeysym(dpy, ev.xkey.keycode, 0, ev.xkey.state & numlock_mask?1:0);
else
ksym = XKeycodeToKeysym(dpy, ev.xkey.keycode, 0);
ksym = XKeycodeToKeysym(dpy, ev.xkey.keycode, ev.xkey.state & numlock_mask?1:0);
if (!IsModifierKey(ksym)) {
if (convert_case) {

View File

@@ -384,7 +384,7 @@ static void fillModifierPopUp(WMPopUpButton * pop)
if (xext_xkb_supported)
ksym = XkbKeycodeToKeysym(dpy, mapping->modifiermap[idx], 0, l);
else
ksym = XKeycodeToKeysym(dpy, mapping->modifiermap[idx], 0);
ksym = XKeycodeToKeysym(dpy, mapping->modifiermap[idx], l);
if (ksym != NoSymbol)
break;
}

View File

@@ -232,6 +232,7 @@
WindowRelaunchKey = None;
ScreenSwitchKey = None;
RunKey = None;
ExitKey = None;
NormalCursor = (builtin, left_ptr);
ArrowCursor = (builtin, top_left_arrow);
MoveCursor = (builtin, fleur);

View File

@@ -387,7 +387,7 @@ AC_FUNC_MEMCMP
AC_FUNC_VPRINTF
WM_FUNC_SECURE_GETENV
AC_CHECK_FUNCS(gethostname select poll strcasecmp strncasecmp \
setsid mallinfo mkstemp sysconf)
setsid mallinfo2 mkstemp sysconf)
AC_SEARCH_LIBS([strerror], [cposix])
dnl nanosleep is generally available in standard libc, although not always the
@@ -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 ==============

View File

@@ -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
# --------------------
#

View File

@@ -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;

View File

@@ -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);

View File

@@ -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,

View File

@@ -36,6 +36,8 @@
#include <dirent.h>
#include <limits.h>
#include <errno.h>
#include <time.h>
#include <sys/utsname.h>
#ifdef HAVE_MALLOC_H
#include <malloc.h>
@@ -1153,7 +1155,7 @@ typedef struct {
#define COPYRIGHT_TEXT \
"Copyright \xc2\xa9 1997-2006 Alfredo K. Kojima\n"\
"Copyright \xc2\xa9 1998-2006 Dan Pascu\n"\
"Copyright \xc2\xa9 2013-2020 Window Maker Developers Team"
"Copyright \xc2\xa9 2013-%hu Window Maker Developers Team"
static InfoPanel *infoPanel = NULL;
@@ -1171,6 +1173,57 @@ static void destroyInfoPanel(WCoreWindow *foo, void *data, XEvent *event)
infoPanel = NULL;
}
char *getPrettyOSName(void)
{
char line[200];
char *token;
char *posn = NULL;
const char s[2] = "=";
FILE *fp;
fp = fopen("/etc/os-release", "r");
if (!fp) {
fp = fopen("/usr/lib/os-release", "r");
if (!fp) {
wwarning(_("no os-release file on the system"));
return NULL;
}
}
while (fgets(line, sizeof(line), fp) != NULL) {
if (strncmp(line, "PRETTY_NAME", strlen("PRETTY_NAME")) == 0) {
line[strcspn(line, "\r\n")] = 0;
token = strtok(line, s);
if (token) {
//get straight to the second part of the line
token = strtok(NULL, s);
if (token) {
//removing potential quotes
char *dst = token;
char *src = token;
char c;
while ((c = *src++) != '\0') {
if (c == '\\') {
*dst++ = c;
if ((c = *src++) == '\0')
break;
*dst++ = c;
} else if (c != '"' && c != '\'')
*dst++ = c;
}
*dst = '\0';
posn = wmalloc(strlen(token) + 1);
strcpy(posn, token);
}
}
break;
}
}
fclose(fp);
return posn;
}
void wShowInfoPanel(WScreen *scr)
{
InfoPanel *panel;
@@ -1194,6 +1247,17 @@ void wShowInfoPanel(WScreen *scr)
};
int wmScaleWidth, wmScaleHeight;
int pwidth, pheight;
int current_year = 2020;
time_t s;
struct tm *current_time;
struct utsname uts;
s = time(NULL);
if (s) {
current_time = localtime(&s);
if (current_time->tm_year > (current_year - 1900))
current_year = current_time->tm_year + 1900;
}
if (infoPanel) {
if (infoPanel->scr == scr) {
@@ -1209,8 +1273,12 @@ void wShowInfoPanel(WScreen *scr)
panel->win = WMCreateWindow(scr->wmscreen, "info");
WMGetScaleBaseFromSystemFont(scr->wmscreen, &wmScaleWidth, &wmScaleHeight);
#if defined(HAVE_MALLOC_H) && defined(HAVE_MALLINFO2) && defined(DEBUG)
pwidth = WMScaleX(412);
#else
pwidth = WMScaleX(382);
pheight = WMScaleY(250);
#endif
pheight = WMScaleY(270);
WMResizeWidget(panel->win, pwidth, pheight);
logo = WMCreateApplicationIconBlendedPixmap(scr->wmscreen, (RColor *) NULL);
@@ -1274,9 +1342,11 @@ void wShowInfoPanel(WScreen *scr)
panel->copyrL = WMCreateLabel(panel->win);
WMResizeWidget(panel->copyrL, WMScaleX(360), WMScaleY(60));
WMMoveWidget(panel->copyrL, WMScaleX(15), WMScaleY(190));
WMMoveWidget(panel->copyrL, WMScaleX(15), WMScaleY(210));
WMSetLabelTextAlignment(panel->copyrL, WALeft);
WMSetLabelText(panel->copyrL, COPYRIGHT_TEXT);
snprintf(buffer, sizeof(buffer), COPYRIGHT_TEXT, current_year);
WMSetLabelText(panel->copyrL, buffer);
font = WMSystemFontOfSize(scr->wmscreen, WMScaleY(11));
if (font) {
WMSetLabelFont(panel->copyrL, font);
@@ -1285,9 +1355,19 @@ void wShowInfoPanel(WScreen *scr)
}
strbuf = NULL;
if (uname(&uts) != -1) {
char *posn = getPrettyOSName();
if (posn) {
snprintf(buffer, sizeof(buffer), _("Running on: %s (%s)\n"), posn, uts.machine);
free(posn);
}
else
snprintf(buffer, sizeof(buffer), _("Running on: %s (%s)\n"), uts.sysname, uts.machine);
strbuf = wstrappend(strbuf, buffer);
}
snprintf(buffer, sizeof(buffer), _("Using visual 0x%x: %s %ibpp "),
(unsigned)scr->w_visual->visualid, visuals[scr->w_visual->class], scr->w_depth);
strbuf = wstrappend(strbuf, buffer);
switch (scr->w_depth) {
@@ -1307,14 +1387,14 @@ void wShowInfoPanel(WScreen *scr)
break;
}
#if defined(HAVE_MALLOC_H) && defined(HAVE_MALLINFO)
#if defined(HAVE_MALLOC_H) && defined(HAVE_MALLINFO2)
{
struct mallinfo ma = mallinfo();
struct mallinfo2 ma = mallinfo2();
snprintf(buffer, sizeof(buffer),
#ifdef DEBUG
_("Total memory allocated: %i kB (in use: %i kB, %d free chunks).\n"),
_("Total memory allocated: %lu kB (in use: %lu kB, %lu free chunks)\n"),
#else
_("Total memory allocated: %i kB (in use: %i kB).\n"),
_("Total memory allocated: %lu kB (in use: %lu kB)\n"),
#endif
(ma.arena + ma.hblkhd) / 1024,
(ma.uordblks + ma.hblkhd) / 1024
@@ -1353,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
@@ -1365,7 +1449,7 @@ void wShowInfoPanel(WScreen *scr)
strbuf = wstrappend(strbuf, _("Xinerama: "));
{
char tmp[128];
snprintf(tmp, sizeof(tmp) - 1, _("%d head(s) found."), scr->xine_info.count);
snprintf(tmp, sizeof(tmp) - 1, _("%d head(s) found"), scr->xine_info.count);
strbuf = wstrappend(strbuf, tmp);
}
#endif
@@ -1377,11 +1461,14 @@ void wShowInfoPanel(WScreen *scr)
strbuf = wstrappend(strbuf, _("supported"));
else
strbuf = wstrappend(strbuf, _("unsupported"));
strbuf = wstrappend(strbuf, ".");
#endif
panel->infoL = WMCreateLabel(panel->win);
WMResizeWidget(panel->infoL, WMScaleX(350), WMScaleY(80));
#if defined(HAVE_MALLOC_H) && defined(HAVE_MALLINFO2) && defined(DEBUG)
WMResizeWidget(panel->infoL, WMScaleX(380), WMScaleY(100));
#else
WMResizeWidget(panel->infoL, WMScaleX(350), WMScaleY(100));
#endif
WMMoveWidget(panel->infoL, WMScaleX(15), WMScaleY(115));
WMSetLabelText(panel->infoL, strbuf);
font = WMSystemFontOfSize(scr->wmscreen, WMScaleY(11));

View File

@@ -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;
}

View File

@@ -422,7 +422,7 @@ static char *get_icon_cache_path(void)
{
const char *prefix;
char *path;
int len, ret;
int ret;
prefix = wuserdatapath();
path = wstrconcat(prefix, CACHE_ICON_PATH "/");

View File

@@ -145,6 +145,9 @@ enum {
/* open "run" dialog */
WKBD_RUN,
/* open "exit" dialog */
WKBD_EXIT,
#ifdef KEEP_XKB_LOCK_STATUS
WKBD_TOGGLE,
#endif

View File

@@ -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;

View File

@@ -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;

View File

@@ -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);

View File

@@ -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"),
_("Exit window manager?"), _("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)

View File

@@ -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)

View File

@@ -61,6 +61,7 @@ struct SwitchPanel {
WMFont *font;
WMColor *white;
WMColor *gray;
};
/* these values will be updated whenever the switch panel
@@ -154,11 +155,9 @@ static void changeImage(WSwitchPanel *panel, int idecks, int selected, Bool dim,
border_space + pos.y, back->width, back->height, 0, 0);
} else {
RColor color;
WMScreen *wscr = WMWidgetScreen(icon);
color.red = 255;
color.red = WMRedComponentOfColor(WMGrayColor(wscr)) >> 8;
color.green = WMGreenComponentOfColor(WMGrayColor(wscr)) >> 8;
color.blue = WMBlueComponentOfColor(WMGrayColor(wscr)) >> 8;
color.red = WMRedComponentOfColor(panel->gray) >> 8;
color.green = WMGreenComponentOfColor(panel->gray) >> 8;
color.blue = WMBlueComponentOfColor(panel->gray) >> 8;
RFillImage(back, &color);
}
@@ -454,6 +453,7 @@ WSwitchPanel *wInitSwitchPanel(WScreen *scr, WWindow *curwin, Bool class_only)
}
panel->white = WMWhiteColor(scr->wmscreen);
panel->gray = WMGrayColor(scr->wmscreen);
panel->font = WMBoldSystemFontOfSize(scr->wmscreen, WMScaleY(12));
panel->icons = WMCreateArray(count);
panel->images = WMCreateArray(count);
@@ -589,6 +589,9 @@ void wSwitchPanelDestroy(WSwitchPanel *panel)
if (panel->white)
WMReleaseColor(panel->white);
if (panel->gray)
WMReleaseColor(panel->gray);
wfree(panel);
}

View File

@@ -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;
@@ -1858,8 +1899,10 @@ void wWindowConstrainSize(WWindow *wwin, unsigned int *nwidth, unsigned int *nhe
int baseH = 0;
if (wwin->normal_hints) {
winc = wwin->normal_hints->width_inc;
hinc = wwin->normal_hints->height_inc;
if (!wwin->flags.maximized) {
winc = wwin->normal_hints->width_inc;
hinc = wwin->normal_hints->height_inc;
}
minW = wwin->normal_hints->min_width;
minH = wwin->normal_hints->min_height;
maxW = wwin->normal_hints->max_width;
@@ -1922,15 +1965,17 @@ void wWindowConstrainSize(WWindow *wwin, unsigned int *nwidth, unsigned int *nhe
}
}
if (baseW != 0)
width = (((width - baseW) / winc) * winc) + baseW;
else
width = (((width - minW) / winc) * winc) + minW;
if (!wwin->flags.maximized) {
if (baseW != 0)
width = (((width - baseW) / winc) * winc) + baseW;
else
width = (((width - minW) / winc) * winc) + minW;
if (baseH != 0)
height = (((height - baseH) / hinc) * hinc) + baseH;
else
height = (((height - minH) / hinc) * hinc) + minH;
if (baseH != 0)
height = (((height - baseH) / hinc) * hinc) + baseH;
else
height = (((height - minH) / hinc) * hinc) + minH;
}
/* broken stupid apps may cause preposterous values for these.. */
if (width > 0)

View File

@@ -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 */

View File

@@ -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;
}

View File

@@ -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*/

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -750,7 +750,7 @@ int main(int argc, char **argv)
dpy = XOpenDisplay(NULL);
if (!dpy) {
fprintf(stderr, "Error: can't open display");
fprintf(stderr, "Error: can't open display\n");
linked_list_free(&list);
return EXIT_FAILURE;
}

View File

@@ -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);
}

View File

@@ -28,6 +28,7 @@
#include <tiff.h>
#include <tiffio.h>
#include <tiffvers.h>
#include "wraster.h"
#include "imgformat.h"
@@ -38,14 +39,19 @@ RImage *RLoadTIFF(const char *file, int index)
{
RImage *image = NULL;
TIFF *tif;
int i;
int i, ch;
unsigned char *r, *g, *b, *a;
uint16 alpha, amode;
#if TIFFLIB_VERSION < 20210416
uint16 alpha, amode, extrasamples;
uint16 *sampleinfo;
uint32 width, height;
uint32 *data, *ptr;
uint16 extrasamples;
uint16 *sampleinfo;
int ch;
#else
uint16_t alpha, amode, extrasamples;;
uint16_t *sampleinfo;
uint32_t width, height;
uint32_t *data, *ptr;
#endif
tif = TIFFOpen(file, "r");
if (!tif)
@@ -79,7 +85,11 @@ RImage *RLoadTIFF(const char *file, int index)
}
/* read data */
#if TIFFLIB_VERSION < 20210416
ptr = data = (uint32 *) _TIFFmalloc(width * height * sizeof(uint32));
#else
ptr = data = (uint32_t *) _TIFFmalloc(width * height * sizeof(uint32_t));
#endif
if (!data) {
RErrorCode = RERR_NOMEMORY;