1
0
mirror of https://github.com/gryf/wmaker.git synced 2026-03-26 15:03:34 +01:00

12 Commits

Author SHA1 Message Date
David Maciejak
038a3588d6 WINGs: W_KeycodeToKeysym remove unnecessary if test
min_kc value is always -1 at that point in the code, so need to test it
as it's always true.
2023-03-09 15:05:58 +00:00
David Maciejak
0b2fd6a8c8 WINGs: handle fixed size windows
According to the EWMH specs, windows can indicate that they are
non-resizable by setting minheight = maxheight and minwidth = maxwidth
in the ICCCM WM_NORMAL_HINTS property. That should be for example
the case for WPrefs app which is not resizable.
Window Maker currently is overwriting that flag in src/window.c for
apps that are exposing GNUstepHints instead.
This patch is making sure the apps created with WINGs is removing
the WMResizableWindowMask to hide the resizebar.
2023-03-09 15:05:58 +00:00
David Maciejak
3e991badf7 SwitchPanel: fix app icons opacity combination
For some apps the background is not displayed properly, showing
some kind of shawow around the app icon like for example firefox
or skype. This is due to an issue in combining alpha channels.
2023-03-09 15:05:58 +00:00
David Maciejak
ac6d284269 NEWS: add entry for libXRes support 2023-03-09 15:05:58 +00:00
David Maciejak
83b94b1616 Update news and changelog files 2023-03-07 17:31:07 +00:00
David Maciejak
d045ffcf7d Add a screenshot capture feature
This patch adds a feature to take screenshots directly from Window Maker.
Having the feature embeded direclty inside Window Maker allows us to take
advantage of how Window Maker is managing and handling Windows.
Three new actions can be bound to a key shortcut from WPrefs.
The screenshot files are saved in ~/GNUstep/Library/WindowMaker/Screenshots/
dir, with a "screenshot_%Y-%m-%d_at_%H:%M:%S" format followed by the
extension. Preferably as a PNG or JPG file if available.
Meaning, to work Window Maker via WRaster needs to support
at least one of those format.

"Capture the entire screen" is quite standard, it takes a screenshot
of the whole screen area (even in multiheads env).
"Capture a portion of the screen" requires the user to draw a rectangle which
will be captured.
Those two first are quite straightforward, just taking a live picture of
the screen.
The last one is "Capture a window" which works in best effort mode,
it catures the focused window. As Window Maker by default is not using
any compositor (like for example Xcompmgr) it can only dump the content
displayed on the screen.
If a window is minimized or out of the screen, there is high chance the
image will be split or some area greyed in case other windows overlapped it.
2023-03-07 17:30:59 +00:00
David Maciejak
6c69dc32a0 WINGs: Make the test examples to compile
Those examples are optional but currently cannot compile properly.
The compiler is reporting some unused variables and missing header file.
2023-03-07 17:24:41 +00:00
David Maciejak
3b1c00ad06 WINGs: comment out wtext unused NOTIFY macro
The compiler is reporting the warning below
wtext.c:171: warning: macro "NOTIFY" is not used [-Wunused-macros]

That macro is only used once within that C file, code which is commented
out already.
2023-03-06 20:16:07 +00:00
David Maciejak
dd6fe27858 WPrefs: convert workspacename.xpm X11 color name to hex
On window maker built without libxpm, a simple build-in xpm support is used.
That component does not support X11 color name thus when trying to load
that image we are getting a file corrupted error.
Colors manually converted using ref at
https://www.ehdp.com/methods/x11-colors/x11-colors-rgb-values-05.htm
2023-03-05 00:16:44 +00:00
David Maciejak
45f3f5d0ae Util: fix wmgenmenu memory leak and help msg
Memory allocated from wstrconcat() calls are not freed properly.
Help msg is reporting the wrong directory where to install WMRootMenu.
2023-03-05 00:16:44 +00:00
David Maciejak
7185af15cf Use wtokenfree whenever there is wtokensplit
Whenever wtokensplit is used to split into argv/argc, it's better to
use the built-in function wtokenfree() as a wfree call only on argv
is not freeing the memory properly.
2023-03-05 00:16:44 +00:00
David Maciejak
80e8dd43f7 Convert tile.xpm X11 color name to hex
On window maker built without libxpm, a simple build-in xpm support is used.
That component does not support X11 color name thus when trying to load
that image we are getting a file corrupted error.
Colors manually converted using ref at
https://www.ehdp.com/methods/x11-colors/x11-colors-rgb-values-05.htm
2023-03-05 00:16:44 +00:00
28 changed files with 398 additions and 53 deletions

28
NEWS
View File

@@ -1,7 +1,32 @@
NEWS for veteran Window Maker users
-----------------------------------
-- 0.95.10
-- 0.96.0
Screenshot capture feature
--------------------------
In WPrefs "Keyboard Shortcut Preferences" tab, three new actions can
be configured: "Capture a portion of the screen", "Capture a window",
"Capture the entire screen". The file is saved in
~/GNUstep/Library/WindowMaker/Screenshots directory under a filename
format "screenshot_%Y-%m-%d_at_%H:%M:%S" followed by the extension.
Which can be png or jpg based on WRaster dependencies.
libXRes is now an optional dependency
-------------------------------------
XRes the resource extension for the X protocol is used to find the
underlying processes (and PIDs) responsible for displaying the windows.
Support for _NET_WM_FULLSCREEN_MONITORS hint
--------------------------------------------
That hint allows applications that support it to be set as fullscreen on multiple heads.
It depends on Xinerama extension support.
Keep dock on primary head
-------------------------
@@ -10,6 +35,7 @@ To keep the dock on the primary head in a multi-head setup, set the option
"KeepDockOnPrimaryHead" in ~/GNUstep/Defaults/WindowMaker to "YES" or click
"Keep dock on primary head" under the WPrefs "Expert User Preferences" tab.
-- 0.95.9
Configurable SwitchPanel

View File

@@ -1,4 +1,4 @@
Changes since wmaker 0.95.10:
Changes since wmaker 0.96.0:
............................
- added W_KeycodeToKeysym to replace XKeycodeToKeysym/XkbKeycodeToKeysym calls

View File

@@ -1,4 +1,4 @@
** API and ABI modifications since wmaker 0.95.10
** API and ABI modifications since wmaker 0.96.0
----------------------------------------------------
** libWINGs **

View File

@@ -17,4 +17,5 @@ wtest_DEPENDENCIES = $(top_builddir)/WINGs/libWINGs.la
EXTRA_DIST = logo.xpm upbtn.xpm wm.html wm.png
AM_CPPFLAGS = -I$(top_srcdir)/WINGs -I$(top_srcdir)/wrlib -I$(top_srcdir)/src \
-DRESOURCE_PATH=\"$(datadir)/WINGs\" @XFT_CFLAGS@ @HEADER_SEARCH_PATH@
-DRESOURCE_PATH=\"$(datadir)/WINGs\" @XFT_CFLAGS@ @HEADER_SEARCH_PATH@ \
@PANGO_CFLAGS@

View File

@@ -64,6 +64,7 @@ static W_Class myWidgetClass = 0;
*/
W_Class InitMyWidget(WMScreen * scr)
{
(void)scr;
/* register our widget with WINGs and get our widget class ID */
if (!myWidgetClass) {
myWidgetClass = W_RegisterUserWidget();

View File

@@ -4,7 +4,7 @@
#include "mywidget.h"
void wAbort()
_Noreturn void wAbort(void)
{
exit(1);
}

View File

@@ -19,14 +19,14 @@
#include "logo.xpm"
void wAbort()
_Noreturn void wAbort(void)
{
exit(1);
}
char *ProgName;
void usage(void)
_Noreturn void usage(void)
{
fprintf(stderr,
"usage:\n"
@@ -53,13 +53,10 @@ int main(int argc, char **argv)
WMPixmap *pixmap;
WMOpenPanel *oPanel;
WMSavePanel *sPanel;
/* RImage *image; */
char *title = NULL;
char *initial = "/";
int ch;
int panelType = OPEN_PANEL_TYPE;
extern char *optarg;
extern int optind;
if (!dpy) {
puts("could not open display");
@@ -96,14 +93,14 @@ int main(int argc, char **argv)
if (panelType == SAVE_PANEL_TYPE) {
sPanel = WMGetSavePanel(scr);
if (WMRunModalFilePanelForDirectory(sPanel, NULL, initial,
/*title */ NULL, NULL) == True)
title, NULL) == True)
printf("%s\n", WMGetFilePanelFileName(sPanel));
else
printf("\n");
} else {
oPanel = WMGetOpenPanel(scr);
if (WMRunModalFilePanelForDirectory(oPanel, NULL, initial,
/*title */ NULL, NULL) == True)
title, NULL) == True)
printf("%s\n", WMGetFilePanelFileName(oPanel));
else
printf("\n");

View File

@@ -11,14 +11,14 @@
#include "logo.xpm"
void wAbort()
_Noreturn void wAbort(void)
{
exit(1);
exit(1);
}
char *ProgName;
void usage(void)
_Noreturn void usage(void)
{
fprintf(stderr,
"usage:\n"
@@ -45,8 +45,6 @@ int main(int argc, char **argv)
char *initial = NULL;
char *result = NULL;
int ch;
extern char *optarg;
extern int optind;
WMInitializeApplication("WMQuery", &argc, argv);

View File

@@ -14,7 +14,7 @@
* This will be called when the application will be terminated because
* of a fatal error (only for memory allocation failures ATM).
*/
void wAbort()
_Noreturn void wAbort(void)
{
exit(1);
}
@@ -25,6 +25,7 @@ int windowCount = 0;
void closeAction(WMWidget * self, void *data)
{
(void)data;
WMDestroyWidget(self);
windowCount--;
printf("window closed, window count = %d\n", windowCount);
@@ -165,10 +166,13 @@ void testBox(WMScreen * scr)
static void singleClick(WMWidget * self, void *data)
{
(void)self;
(void)data;
}
static void doubleClick(WMWidget * self, void *data)
{
(void)data;
WMSelectAllListItems((WMList *) self);
}
@@ -480,6 +484,7 @@ void testColorPanel(WMScreen * scr)
void sliderCallback(WMWidget * w, void *data)
{
(void)data;
printf("SLIDER == %i\n", WMGetSliderValue(w));
}
@@ -749,6 +754,8 @@ void testTabView(WMScreen * scr)
void splitViewConstrainProc(WMSplitView * sPtr, int indView, int *minSize, int *maxSize)
{
(void)sPtr;
switch (indView) {
case 0:
*minSize = 20;
@@ -782,6 +789,7 @@ static void resizeSplitView(XEvent * event, void *data)
void appendSubviewButtonAction(WMWidget * self, void *data)
{
(void)self;
WMSplitView *sPtr = (WMSplitView *) data;
char buf[64];
WMLabel *label = WMCreateLabel(sPtr);
@@ -796,6 +804,7 @@ void appendSubviewButtonAction(WMWidget * self, void *data)
void removeSubviewButtonAction(WMWidget * self, void *data)
{
(void)self;
WMSplitView *sPtr = (WMSplitView *) data;
int count = WMGetSplitViewSubviewsCount(sPtr);
@@ -808,12 +817,14 @@ void removeSubviewButtonAction(WMWidget * self, void *data)
void orientationButtonAction(WMWidget * self, void *data)
{
(void)self;
WMSplitView *sPtr = (WMSplitView *) data;
WMSetSplitViewVertical(sPtr, !WMGetSplitViewVertical(sPtr));
}
void adjustSubviewsButtonAction(WMWidget * self, void *data)
{
(void)self;
WMAdjustSplitViewSubviews((WMSplitView *) data);
}
@@ -902,7 +913,7 @@ void testSplitView(WMScreen * scr)
WMMapWidget(win);
}
void testUD()
void testUD(void)
{
WMUserDefaults *defs;
char str[32];

View File

@@ -226,10 +226,7 @@ KeySym W_KeycodeToKeysym(Display *display, KeyCode keycode, int index)
KeySym *key_syms;
KeySym ks;
if (min_kc == -1) {
(void) XDisplayKeycodes(display, &min_kc, &max_kc);
}
XDisplayKeycodes(display, &min_kc, &max_kc);
if (keycode < min_kc || keycode > max_kc || index < 0) {
return NoSymbol;
}

View File

@@ -166,12 +166,15 @@ typedef struct W_Text {
WMArray *xdndDestinationTypes;
} Text;
/* not used */
#if 0
#define NOTIFY(T,C,N,A) {\
WMNotification *notif = WMCreateNotification(N,T,A);\
if ((T)->delegate && (T)->delegate->C)\
(*(T)->delegate->C)((T)->delegate,notif);\
WMPostNotification(notif);\
WMReleaseNotification(notif);}
#endif
#define TYPETEXT 0

View File

@@ -395,7 +395,11 @@ static void setWindowMakerHints(WMWindow * win)
memset(&attribs, 0, sizeof(GNUstepWMAttributes));
attribs.flags = GSWindowStyleAttr | GSWindowLevelAttr | GSExtraFlagsAttr;
if (win->minSize.width == win->maxSize.width && win->minSize.height == win->maxSize.height)
win->flags.style &= ~WMResizableWindowMask;
attribs.window_style = win->flags.style;
attribs.window_level = win->level;
if (win->flags.documentEdited)
attribs.extra_flags = GSDocumentEditedFlag;

View File

@@ -158,7 +158,10 @@ static struct keyOption {
{ "RunKey", N_("Run application") },
{ "ExitKey", N_("Exit Window Maker") },
{ "DockRaiseLowerKey", N_("Raise/Lower Dock") },
{ "ClipRaiseLowerKey", N_("Raise/Lower Clip") }
{ "ClipRaiseLowerKey", N_("Raise/Lower Clip") },
{ "ScreenCaptureKey", N_("Capture the entire screen") },
{ "WindowCaptureKey", N_("Capture a window") },
{ "PartialCaptureKey", N_("Capture a portion of the screen") }
#ifdef XKB_MODELOCK
,{ "ToggleKbdModeKey", N_("Toggle keyboard language") }
#endif /* XKB_MODELOCK */

View File

@@ -2,9 +2,9 @@
static char *magick[] = {
/* columns rows colors chars-per-pixel */
"50 40 95 2",
" c Gray0",
" c #000000",
". c #010101",
"X c Gray2",
"X c #050505",
"o c #040406",
"O c #070707",
"+ c #0a0a0d",
@@ -20,14 +20,14 @@ static char *magick[] = {
": c #4e4e4e",
"> c #505055",
", c #585858",
"< c Gray37",
"< c #5e5e5e",
"1 c #494d62",
"2 c #545066",
"3 c #57556f",
"4 c #5d627c",
"5 c #604e42",
"6 c Gray39",
"7 c Gray41",
"6 c #636363",
"7 c #696969",
"8 c #646475",
"9 c #7e6a63",
"0 c #75746d",
@@ -67,36 +67,36 @@ static char *magick[] = {
"D c #989799",
"F c #9b9b9b",
"G c #999e98",
"H c Gray62",
"H c #9e9e9e",
"J c #9e9f9f",
"K c #8d8cba",
"L c #9995a0",
"P c #a2a2a3",
"I c #a7a7a8",
"U c Gray66",
"U c #a8a8a8",
"Y c #acacac",
"T c Gray68",
"R c Gray69",
"T c #adadad",
"R c #b0b0b0",
"E c #b2b2b2",
"W c #b4b4b4",
"Q c Gray71",
"Q c #b5b5b5",
"! c #b9b9b9",
"~ c Gray73",
"~ c #bababa",
"^ c #bbbbbb",
"/ c #a7a7c5",
"( c #acadcf",
") c #c0c0c0",
"_ c #c3c3c3",
"` c #c8c8c8",
"' c Gray79",
"] c Gray80",
"' c #c9c9c9",
"] c #cccccc",
"[ c #dfdfdf",
"{ c #e2e2e2",
"} c Gray91",
"} c #e8e8e8",
"| c #e9e9e9",
" . c Gray95",
" . c #f2f2f2",
".. c #fbfbfb",
"X. c Gray100",
"X. c #ffffff",
/* pixels */
"$ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ } ",
"$ 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 } } } } } } } } ",

View File

@@ -233,6 +233,9 @@
ScreenSwitchKey = None;
RunKey = None;
ExitKey = None;
ScreenCaptureKey = Print;
WindowCaptureKey = None;
PartialCaptureKey = None;
NormalCursor = (builtin, left_ptr);
ArrowCursor = (builtin, top_left_arrow);
MoveCursor = (builtin, fleur);

View File

@@ -6,9 +6,9 @@ static char *magick[] = {
". c #ededee",
"X c #e7e7e7",
"o c #e2e2e2",
"O c gray87",
"+ c gray85",
"@ c gray76",
"O c #dedede",
"+ c #d9d9d9",
"@ c #c2c2c2",
"# c #010101",
"$ c #4d505a",
"% c #e0e0e6",

View File

@@ -119,6 +119,7 @@ typedef enum {
WCUR_QUESTION,
WCUR_TEXT,
WCUR_SELECT,
WCUR_CAPTURE,
WCUR_ROOT,
WCUR_EMPTY,

View File

@@ -790,6 +790,12 @@ WDefaultEntry optionList[] = {
NULL, getKeybind, setKeyGrab, NULL, NULL},
{"ExitKey", "None", (void *)WKBD_EXIT,
NULL, getKeybind, setKeyGrab, NULL, NULL},
{"ScreenCaptureKey", "None", (void *)WKBD_PRINTS,
NULL, getKeybind, setKeyGrab, NULL, NULL},
{"WindowCaptureKey", "None", (void *)WKBD_PRINTW,
NULL, getKeybind, setKeyGrab, NULL, NULL},
{"PartialCaptureKey", "None", (void *)WKBD_PRINTP,
NULL, getKeybind, setKeyGrab, NULL, NULL},
#ifdef KEEP_XKB_LOCK_STATUS
{"ToggleKbdModeKey", "None", (void *)WKBD_TOGGLE,
@@ -826,6 +832,8 @@ WDefaultEntry optionList[] = {
NULL, getCursor, setCursor, NULL, NULL},
{"SelectCursor", "(builtin, cross)", (void *)WCUR_SELECT,
NULL, getCursor, setCursor, NULL, NULL},
{"CaptureCursor", "(builtin, crosshair)", (void *)WCUR_CAPTURE,
NULL, getCursor, setCursor, NULL, NULL},
{"DialogHistoryLines", "500", NULL,
&wPreferences.history_lines, getInt, NULL, NULL, NULL},
{"CycleActiveHeadOnly", "NO", NULL,

View File

@@ -1863,6 +1863,24 @@ static void handleKeyPress(XEvent * event)
break;
}
case WKBD_PRINTS:
{
ScreenCapture(scr, PRINT_SCREEN);
break;
}
case WKBD_PRINTW:
{
ScreenCapture(scr, PRINT_WINDOW);
break;
}
case WKBD_PRINTP:
{
ScreenCapture(scr, PRINT_PARTIAL);
break;
}
case WKBD_NEXTWSLAYER:
case WKBD_PREVWSLAYER:
{

View File

@@ -148,6 +148,15 @@ enum {
/* open "exit" dialog */
WKBD_EXIT,
/* screen print */
WKBD_PRINTS,
/* window print */
WKBD_PRINTW,
/* partial print */
WKBD_PRINTP,
#ifdef KEEP_XKB_LOCK_STATUS
WKBD_TOGGLE,
#endif

View File

@@ -393,7 +393,7 @@ Bool RelaunchWindow(WWindow *wwin)
} else if (pid < 0) {
werror("cannot fork a new process");
wfree(argv);
wtokenfree(argv, argc);
wfree(command);
return False;
} else {
@@ -405,7 +405,7 @@ Bool RelaunchWindow(WWindow *wwin)
/* not actually a shell command */
wAddDeathHandler(pid, shellCommandHandler, data);
wfree(argv);
wtokenfree(argv, argc);
}
return True;

View File

@@ -24,6 +24,10 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <errno.h>
#include <sys/stat.h>
#include <unistd.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
@@ -54,10 +58,12 @@
#include "geomview.h"
#include "wmspec.h"
#include "rootmenu.h"
#include "misc.h"
#include "xinerama.h"
#include <WINGs/WUtil.h>
#include <WINGs/WINGsP.h>
#include "defaults.h"
@@ -593,6 +599,7 @@ static void createInternalWindows(WScreen * scr)
scr->workspace_name =
XCreateWindow(dpy, scr->root_win, 0, 0, 10, 10, 0, scr->w_depth,
CopyFromParent, scr->w_visual, vmask, &attribs);
scr->mini_screenshot_timeout = 0;
}
/*
@@ -1126,3 +1133,246 @@ int wScreenKeepInside(WScreen * scr, int *x, int *y, int width, int height)
return moved;
}
static XImage *imageCaptureArea(WScreen *scr)
{
XEvent event;
int quit = 0;
int xp = -1;
int yp = -1;
int w = 0, h = 0;
int x = xp, y = yp;
if (XGrabPointer(dpy, scr->root_win, False, ButtonMotionMask
| ButtonReleaseMask | ButtonPressMask, GrabModeAsync,
GrabModeAsync, None, wPreferences.cursor[WCUR_CAPTURE], CurrentTime) != Success) {
return NULL;
}
XGrabServer(dpy);
while (!quit) {
WMMaskEvent(dpy, ButtonReleaseMask | PointerMotionMask | ButtonPressMask | KeyPressMask, &event);
switch (event.type) {
case ButtonPress:
if (event.xbutton.button == Button1) {
xp = event.xbutton.x_root;
yp = event.xbutton.y_root;
}
break;
case ButtonRelease:
if (event.xbutton.button == Button1) {
quit = 1;
if (w > 0 && h > 0) {
XDrawRectangle(dpy, scr->root_win, scr->frame_gc, x, y, w, h);
XUngrabServer(dpy);
XUngrabPointer(dpy, CurrentTime);
return XGetImage(dpy, scr->root_win, x, y, w, h, AllPlanes, ZPixmap);
}
}
break;
case MotionNotify:
XDrawRectangle(dpy, scr->root_win, scr->frame_gc, x, y, w, h);
x = event.xmotion.x_root;
if (x < xp) {
w = xp - x;
} else {
w = x - xp;
x = xp;
}
y = event.xmotion.y_root;
if (y < yp) {
h = yp - y;
} else {
h = y - yp;
y = yp;
}
XDrawRectangle(dpy, scr->root_win, scr->frame_gc, x, y, w, h);
break;
case KeyPress:
if (W_KeycodeToKeysym(dpy, event.xkey.keycode, 0) == XK_Escape)
quit = 1;
break;
default:
WMHandleEvent(&event);
break;
}
}
XUngrabServer(dpy);
XUngrabPointer(dpy, CurrentTime);
return NULL;
}
static void hideMiniScreenshot(void *data)
{
WScreen *scr = (WScreen *) data;
if (time(NULL) < scr->mini_screenshot_timeout) {
scr->mini_screenshot_timer = WMAddTimerHandler(WORKSPACE_NAME_FADE_DELAY, hideMiniScreenshot, scr);
} else {
XWindowAttributes attr;
WMDeleteTimerHandler(scr->mini_screenshot_timer);
if (XGetWindowAttributes(dpy, scr->mini_screenshot, &attr))
slide_window(scr->mini_screenshot, attr.x, attr.y, attr.x + attr.width, attr.y);
XUnmapWindow(dpy, scr->mini_screenshot);
XDestroyWindow(dpy, scr->mini_screenshot);
scr->mini_screenshot_timeout = 0;
}
}
static void showMiniScreenshot(WScreen *scr, RImage *img)
{
Pixmap pix;
int x = scr->scr_width - img->width - 20;
int y = scr->scr_height - img->height - 20;
if (!scr->mini_screenshot_timeout) {
Window win;
win = XCreateSimpleWindow(dpy, scr->root_win, x, y,
img->width, img->height, scr->frame_border_width, 0, 0);
scr->mini_screenshot = win;
}
RConvertImage(scr->rcontext, img, &pix);
XMapWindow(dpy, scr->mini_screenshot);
XCopyArea(dpy, pix, scr->mini_screenshot, scr->rcontext->copy_gc, 0, 0, img->width, img->height, 0, 0);
XFlush(dpy);
scr->mini_screenshot_timeout = time(NULL) + 2;
scr->mini_screenshot_timer = WMAddTimerHandler(WORKSPACE_NAME_FADE_DELAY, hideMiniScreenshot, scr);
}
void ScreenCapture(WScreen *scr, int mode)
{
time_t s;
short i = 0;
struct tm *tm_info;
char index_str[12] = "";
char filename_date_part[60];
char filename[60];
char *filepath;
char *screenshot_dir;
RImage *img = NULL;
RImage *scale_img = NULL;
#ifdef USE_PNG
char *filetype = ".png";
#else
#ifdef USE_JPEG
char *filetype = ".jpg";
#else
char *filetype = NULL;
#endif
#endif
if (!filetype) {
werror(_("Unable to find a proper screenshot image format"));
return;
}
screenshot_dir = wstrconcat(wusergnusteppath(), "/Library/WindowMaker/Screenshots/");
if (-1 == mkdir(screenshot_dir, 0700) && errno != EEXIST) {
wfree(screenshot_dir);
werror(_("Unable to create screenshot directory: %s"), strerror(errno));
return;
}
s = time(NULL);
tm_info = localtime(&s);
strftime(filename_date_part, sizeof(filename_date_part), "screenshot_%Y-%m-%d_at_%H:%M:%S", tm_info);
strcpy(filename, filename_date_part);
filepath = wstrconcat(screenshot_dir, strcat(filename, filetype));
while (access(filepath, F_OK) == 0 && i < 600) {
i++;
strcpy(filename, filename_date_part);
sprintf(index_str, "_%d", i);
strncat(filename, index_str, sizeof(filename) - strlen(filename) - 1);
wfree(filepath);
filepath = wstrconcat(screenshot_dir, strcat(filename, filetype));
}
/* cannot generate an available filename ?! */
if (i == 600) {
wfree(filepath);
wfree(screenshot_dir);
werror(_("Could not generate a free screenshot filename"));
return;
}
switch (mode) {
case PRINT_WINDOW:
WWindow *wwin = scr->focused_window;
if (wwin && !wwin->flags.shaded) {
/*
* check if hint WM_TAKE_FOCUS is set, if it's the case
* we can take screenshot of the out of screen window
*/
if (wwin->focus_mode >= WFM_LOCALLY_ACTIVE) {
img = RCreateImageFromDrawable(scr->rcontext, wwin->client_win, None);
}
else {
/* we will only capture the visible window part */
XImage *pimg;
int x_crop = 0;
int y_crop = 0;
int w_crop = wwin->client.width;
int h_crop = wwin->client.height;
if (wwin->client.x > 0)
x_crop = wwin->client.x;
if (wwin->client.y > 0)
y_crop = wwin->client.y;
if (wwin->client.x + wwin->client.width > scr->scr_width)
w_crop = scr->scr_width - wwin->client.x;
if (wwin->client.y + wwin->client.height > scr->scr_height)
h_crop = scr->scr_height - wwin->client.y;
pimg = XGetImage(dpy, scr->root_win, x_crop, y_crop,
(wwin->client.x > 0)?w_crop:w_crop + wwin->client.x,
(wwin->client.y > 0)?h_crop:h_crop + wwin->client.y,
AllPlanes, ZPixmap);
if (pimg) {
img = RCreateImageFromXImage(scr->rcontext, pimg, None);
XDestroyImage(pimg);
}
}
}
break;
case PRINT_PARTIAL:
XImage *pimg;
pimg = imageCaptureArea(scr);
if (pimg) {
img = RCreateImageFromXImage(scr->rcontext, pimg, None);
XDestroyImage(pimg);
}
break;
default:
/* PRINT_SCREEN*/
img = RCreateImageFromDrawable(scr->rcontext, scr->root_win, None);
}
if (img) {
#ifdef USE_PNG
if (RSaveTitledImage(img, filepath, (char *)(filetype + 1), "Screenshot from Window Maker")) {
#else
if (RSaveTitledImage(img, filepath, (char *)(filetype + 1), "Screenshot from Window Maker")) {
#endif
scale_img = RSmoothScaleImage(img, scr->scr_width / 10, scr->scr_height / 10);
showMiniScreenshot(scr, scale_img);
RReleaseImage(scale_img);
#ifdef DEBUG
wmessage("screenshot filepath: %s", filepath);
#endif
}
RReleaseImage(img);
}
wfree(filepath);
wfree(screenshot_dir);
}

View File

@@ -27,6 +27,9 @@
#include <WINGs/WUtil.h>
#define PRINT_SCREEN 1
#define PRINT_WINDOW 2
#define PRINT_PARTIAL 3
typedef struct {
WMRect *screens;
@@ -271,6 +274,11 @@ typedef struct _WScreen {
WMHandlerID *workspace_name_timer;
struct WorkspaceNameData *workspace_name_data;
/* mini screenshot data */
Window mini_screenshot;
time_t mini_screenshot_timeout;
WMHandlerID *mini_screenshot_timer;
/* for raise-delay */
WMHandlerID *autoRaiseTimer;
Window autoRaiseWindow; /* window that is scheduled to be
@@ -314,7 +322,7 @@ void wScreenRestoreState(WScreen *scr);
int wScreenBringInside(WScreen *scr, int *x, int *y, int width, int height);
int wScreenKeepInside(WScreen *scr, int *x, int *y, int width, int height);
void ScreenCapture(WScreen *scr, int mode);
/* in startup.c */
WScreen *wScreenWithNumber(int i);

View File

@@ -392,9 +392,7 @@ static pid_t execCommand(WScreen *scr, char *command)
execvp(argv[0], args);
exit(111);
}
while (argc > 0)
wfree(argv[--argc]);
wfree(argv);
wtokenfree(argv, argc);
return pid;
}

View File

@@ -493,6 +493,7 @@ void StartUp(Bool defaultScreenOnly)
wPreferences.cursor[WCUR_QUESTION] = XCreateFontCursor(dpy, XC_question_arrow);
wPreferences.cursor[WCUR_TEXT] = XCreateFontCursor(dpy, XC_xterm); /* odd name??? */
wPreferences.cursor[WCUR_SELECT] = XCreateFontCursor(dpy, XC_cross);
wPreferences.cursor[WCUR_CAPTURE] = XCreateFontCursor(dpy, XC_crosshair);
Pixmap cur = XCreatePixmap(dpy, DefaultRootWindow(dpy), 16, 16, 1);
GC gc = XCreateGC(dpy, cur, 0, NULL);

View File

@@ -158,6 +158,7 @@ static void changeImage(WSwitchPanel *panel, int idecks, int selected, Bool dim,
color.red = WMRedComponentOfColor(panel->gray) >> 8;
color.green = WMGreenComponentOfColor(panel->gray) >> 8;
color.blue = WMBlueComponentOfColor(panel->gray) >> 8;
color.alpha = 255;
RFillImage(back, &color);
}

View File

@@ -379,8 +379,14 @@ int main(int argc, char *argv[])
);
WMAddToPLArray(RMenu, L1Menu);
printf("%s", WMGetPropListDescription(RMenu, True));
puts("");
wfree(tmp);
wfree(theme_paths);
wfree(style_paths);
wfree(icon_paths);
tmp = WMGetPropListDescription(RMenu, True);
printf("%s\n", tmp);
wfree(tmp);
return 0;
}
@@ -451,7 +457,7 @@ static void find_and_write(const char *group, char *list[][2], int this_is_termi
WMAddToPLArray(L2Menu, L3Menu);
wfree(t);
}
wfree(argv);
wtokenfree(argv, argc);
i++;
}
if (L2Menu)
@@ -504,7 +510,7 @@ noreturn void print_help(int print_usage, int exitval)
{
printf("Usage: %s [-h] [-v]\n", prog_name);
if (print_usage) {
puts("Writes a menu structure usable as ~/" GSUSER_SUBDIR "/" USERDATA_SUBDIR "/WMRootMenu to stdout");
puts("Writes a menu structure usable as ~/" GSUSER_SUBDIR "/" DEFAULTS_SUBDIR "/WMRootMenu to stdout");
puts("");
puts(" -h, --help display this help and exit");
puts(" -v, --version output version information and exit");

View File

@@ -1,5 +1,6 @@
** API and ABI modifications
----------------------------------------------------
Since wmaker 0.96.0
Sat 25 Feb 2023