mirror of
https://github.com/gryf/wmaker.git
synced 2026-07-08 19:56:36 +02:00
Compare commits
53 Commits
da676c9e9e
...
cc0a652ea8
| Author | SHA1 | Date | |
|---|---|---|---|
| cc0a652ea8 | |||
| 80079cd343 | |||
| 955c6793a6 | |||
| 189679b49c | |||
| e45a3bc07d | |||
| bc16a03722 | |||
| 260415eb42 | |||
| c8174a4b2e | |||
| 2901b418ad | |||
| ae6b03e50f | |||
| 128ba2ddc7 | |||
| 7ca96b9ed6 | |||
| 839061a25a | |||
| 1e63c590b6 | |||
| 92e1e9fb0b | |||
| ddf0b20367 | |||
| d303317a31 | |||
| c620b354b5 | |||
| ebac2bbcd8 | |||
| 3281349f8d | |||
| 3f5280987e | |||
| 6d0953bc22 | |||
| ef1a504898 | |||
| 474b23344a | |||
| 77db6dc649 | |||
| b09ac30233 | |||
| 6e14b6142b | |||
| 7778df2fc5 | |||
| 156841f80e | |||
| c82e6dad5c | |||
| 95c68fe26d | |||
| 77c3b95fd5 | |||
| b662d0827c | |||
| a542934e67 | |||
| d2b2c3238b | |||
| d37a3162e0 | |||
| 9ddacfc29b | |||
| 7e21785710 | |||
| 7cfdf6bd68 | |||
| 72942267aa | |||
| ac19c4bc07 | |||
| 14bd13b1be | |||
| afe13d3e72 | |||
| e356ef8c05 | |||
| 3d993a7323 | |||
| a4a6e65ca9 | |||
| 4392fdc291 | |||
| 67e2f5e1ca | |||
| 3579c85af1 | |||
| 896bbce2e5 | |||
| 8f1ee27595 | |||
| 541947e9ef | |||
| 7bb7d0f4d6 |
@@ -15,7 +15,7 @@ Summary of Contents:
|
|||||||
1.2 Where can I get Window Maker?
|
1.2 Where can I get Window Maker?
|
||||||
1.3 Where are the mailing list archives?
|
1.3 Where are the mailing list archives?
|
||||||
1.4 Where is more documentation on configuring Window Maker?
|
1.4 Where is more documentation on configuring Window Maker?
|
||||||
1.5 What is an App Icon?
|
1.5 What is an appicon?
|
||||||
1.6 How can I get a question added to the FAQ?
|
1.6 How can I get a question added to the FAQ?
|
||||||
1.7 How do I report bugs?
|
1.7 How do I report bugs?
|
||||||
1.8 Is there an anonymous cvs server?
|
1.8 Is there an anonymous cvs server?
|
||||||
@@ -134,7 +134,7 @@ Introduction:
|
|||||||
|
|
||||||
1.1 What is Window Maker?
|
1.1 What is Window Maker?
|
||||||
----------------------------------
|
----------------------------------
|
||||||
Window Maker is an elegant X11 window manger that emulates the
|
Window Maker is an elegant X11 window manager that emulates the
|
||||||
OpenStep desktop with some noticeable enhancements. Look at
|
OpenStep desktop with some noticeable enhancements. Look at
|
||||||
http://wm.current.nu/themes/my-themes.html and
|
http://wm.current.nu/themes/my-themes.html and
|
||||||
http://wm.current.nu/themes/screenshots.html
|
http://wm.current.nu/themes/screenshots.html
|
||||||
@@ -507,7 +507,7 @@ exec wmaker
|
|||||||
Things to try if it doesn't work: (somewhat fuzzy and random)
|
Things to try if it doesn't work: (somewhat fuzzy and random)
|
||||||
|
|
||||||
This should do it although I did have problems sometimes initially which I
|
This should do it although I did have problems sometimes initially which I
|
||||||
fixed by randomly trying absolute pathes for wmaker in .xsession/.xinitrc and/or
|
fixed by randomly trying absolute paths for wmaker in .xsession/.xinitrc and/or
|
||||||
making the dtprofile/.xinitrc/etc executable. It helps logging in on the console
|
making the dtprofile/.xinitrc/etc executable. It helps logging in on the console
|
||||||
(select from CDE login screen) and start X manually using 'X'.
|
(select from CDE login screen) and start X manually using 'X'.
|
||||||
If it works that way it should work when logging into the CDE environment.
|
If it works that way it should work when logging into the CDE environment.
|
||||||
@@ -628,7 +628,7 @@ the last app started by .xinitrc is closed.
|
|||||||
the X server will be closed, and your session will end.
|
the X server will be closed, and your session will end.
|
||||||
|
|
||||||
|
|
||||||
3.3 How do I "dock" AppIcons on the Clip?
|
3.3 How do I "dock" appicons on the Clip?
|
||||||
-----------------------------------------
|
-----------------------------------------
|
||||||
Just drag icons near it like you would for the dock. Note that if you place
|
Just drag icons near it like you would for the dock. Note that if you place
|
||||||
the clip near the dock, you may have problems docking appicons in either.
|
the clip near the dock, you may have problems docking appicons in either.
|
||||||
@@ -674,7 +674,7 @@ David Reviejo <dreviejo@arrakis.es> best summed up this answer:
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
3.7 How do I "undock" AppIcons?
|
3.7 How do I "undock" appicons?
|
||||||
----------------------------------
|
----------------------------------
|
||||||
If the program is not running, just drag the icon to the middle of your
|
If the program is not running, just drag the icon to the middle of your
|
||||||
desktop (away from the dock and clip) and watch it disappear.
|
desktop (away from the dock and clip) and watch it disappear.
|
||||||
@@ -731,7 +731,7 @@ These directories will be listed under the "Search Path" section of WPrefs.
|
|||||||
3.11 When I run GNOME application they have no title bar.
|
3.11 When I run GNOME application they have no title bar.
|
||||||
----------------------------------
|
----------------------------------
|
||||||
|
|
||||||
The GNOME toolkit decided to behave his own way, so it draws its own title bar
|
The GNOME toolkit decided to behave in its own way, so it draws its own title bar
|
||||||
with buttons, and asks Window Maker to not draw anything (title bar, resize bar,
|
with buttons, and asks Window Maker to not draw anything (title bar, resize bar,
|
||||||
close and miniaturise button, ...).
|
close and miniaturise button, ...).
|
||||||
|
|
||||||
@@ -838,7 +838,7 @@ AlwaysUserIcon=Yes;
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
4.6 How do I get a Tile background for my AppIcons (those things in
|
4.6 How do I get a Tile background for my appicons (those things in
|
||||||
the dock)?
|
the dock)?
|
||||||
----------------------------------
|
----------------------------------
|
||||||
You need to change 1 line to your ~/GNUstep/Defaults/WindowMaker file.
|
You need to change 1 line to your ~/GNUstep/Defaults/WindowMaker file.
|
||||||
@@ -868,9 +868,9 @@ Application Icon'' Option then Save, Apply and close the dialog.
|
|||||||
|
|
||||||
This should allow you do dock the program normally.
|
This should allow you do dock the program normally.
|
||||||
|
|
||||||
Emulate Appicon does exactly the same thing as dockit, a small app
|
Emulate AppIcon does exactly the same thing as dockit, a small app
|
||||||
distributed with ancient versions of Window Maker before the Attribute
|
distributed with ancient versions of Window Maker before the Attribute
|
||||||
Editor existed (now deprecated for the obvious reason). If Emulate Appicon
|
Editor existed (now deprecated for the obvious reason). If Emulate AppIcon
|
||||||
does not work, dockit will not work either. Such applications violate the
|
does not work, dockit will not work either. Such applications violate the
|
||||||
ICCCM (Inter-Client Communication Conventions Manual) and are considered
|
ICCCM (Inter-Client Communication Conventions Manual) and are considered
|
||||||
badly coded for not setting the instance.class hints.
|
badly coded for not setting the instance.class hints.
|
||||||
@@ -898,7 +898,7 @@ NoAppIcon=Yes;
|
|||||||
|
|
||||||
4.9 How do I set a pixmap background?
|
4.9 How do I set a pixmap background?
|
||||||
----------------------------------
|
----------------------------------
|
||||||
Here is the in depth explanation straight from the NEWS file:
|
Here is the in-depth explanation straight from the NEWS file:
|
||||||
|
|
||||||
wmsetbg now accepts the following options:
|
wmsetbg now accepts the following options:
|
||||||
usage: wmsetbg [-options] image
|
usage: wmsetbg [-options] image
|
||||||
@@ -1476,7 +1476,7 @@ Themes:
|
|||||||
8.1 What exactly are themes?
|
8.1 What exactly are themes?
|
||||||
----------------------------------
|
----------------------------------
|
||||||
Themes are a great aspect of Window Maker allowing a user to simply
|
Themes are a great aspect of Window Maker allowing a user to simply
|
||||||
save the entire 'look' of their desktop in a Archive to distribute freely among
|
save the entire 'look' of their desktop in an archive to distribute freely among
|
||||||
friends, fellow users and/or the whole net in general. :)
|
friends, fellow users and/or the whole net in general. :)
|
||||||
|
|
||||||
See the theme-HOWTO at http://wm.current.nu/themes/theme-HOWTO.html
|
See the theme-HOWTO at http://wm.current.nu/themes/theme-HOWTO.html
|
||||||
|
|||||||
@@ -24,8 +24,9 @@
|
|||||||
#include <WINGs/WINGs.h>
|
#include <WINGs/WINGs.h>
|
||||||
#include <WINGs/WUtil.h>
|
#include <WINGs/WUtil.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
#include <stdnoreturn.h>
|
||||||
|
|
||||||
void wAbort()
|
noreturn void wAbort(void)
|
||||||
{
|
{
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
@@ -40,7 +41,7 @@ void show(WMWidget * self, void *data)
|
|||||||
WMSetLabelText(l, buf);
|
WMSetLabelText(l, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
void quit(WMWidget * self, void *data)
|
noreturn void quit(WMWidget * self, void *data)
|
||||||
{
|
{
|
||||||
(void) self;
|
(void) self;
|
||||||
(void) data;
|
(void) data;
|
||||||
|
|||||||
+6
-1
@@ -521,7 +521,7 @@ void testSlider(WMScreen * scr)
|
|||||||
void testTextField(WMScreen * scr)
|
void testTextField(WMScreen * scr)
|
||||||
{
|
{
|
||||||
WMWindow *win;
|
WMWindow *win;
|
||||||
WMTextField *field, *field2;
|
WMTextField *field, *field2, *field3;
|
||||||
|
|
||||||
windowCount++;
|
windowCount++;
|
||||||
|
|
||||||
@@ -540,6 +540,11 @@ void testTextField(WMScreen * scr)
|
|||||||
WMMoveWidget(field2, 20, 50);
|
WMMoveWidget(field2, 20, 50);
|
||||||
WMSetTextFieldAlignment(field2, WARight);
|
WMSetTextFieldAlignment(field2, WARight);
|
||||||
|
|
||||||
|
field3 = WMCreateTextField(win);
|
||||||
|
WMResizeWidget(field3, 200, 20);
|
||||||
|
WMMoveWidget(field3, 20, 80);
|
||||||
|
WMSetTextFieldAlignment(field3, WACenter);
|
||||||
|
|
||||||
WMRealizeWidget(win);
|
WMRealizeWidget(win);
|
||||||
WMMapSubwidgets(win);
|
WMMapSubwidgets(win);
|
||||||
WMMapWidget(win);
|
WMMapWidget(win);
|
||||||
|
|||||||
@@ -1462,6 +1462,10 @@ void WMSetPopUpButtonEnabled(WMPopUpButton *bPtr, Bool flag);
|
|||||||
|
|
||||||
Bool WMGetPopUpButtonEnabled(WMPopUpButton *bPtr);
|
Bool WMGetPopUpButtonEnabled(WMPopUpButton *bPtr);
|
||||||
|
|
||||||
|
int WMSelectPopUpButtonPreviousItem(WMPopUpButton *bPtr);
|
||||||
|
|
||||||
|
int WMSelectPopUpButtonNextItem(WMPopUpButton *bPtr);
|
||||||
|
|
||||||
/* ---[ WINGs/wprogressindicator.c ]------------------------------------- */
|
/* ---[ WINGs/wprogressindicator.c ]------------------------------------- */
|
||||||
|
|
||||||
WMProgressIndicator* WMCreateProgressIndicator(WMWidget *parent);
|
WMProgressIndicator* WMCreateProgressIndicator(WMWidget *parent);
|
||||||
@@ -1529,6 +1533,8 @@ void WMSetScrollViewRelief(WMScrollView *sPtr, WMReliefType type);
|
|||||||
|
|
||||||
WMRect WMGetScrollViewVisibleRect(WMScrollView *sPtr);
|
WMRect WMGetScrollViewVisibleRect(WMScrollView *sPtr);
|
||||||
|
|
||||||
|
void WMScrollViewScrollPoint(WMScrollView * sPtr, WMPoint point);
|
||||||
|
|
||||||
WMScroller* WMGetScrollViewHorizontalScroller(WMScrollView *sPtr);
|
WMScroller* WMGetScrollViewHorizontalScroller(WMScrollView *sPtr);
|
||||||
|
|
||||||
WMScroller* WMGetScrollViewVerticalScroller(WMScrollView *sPtr);
|
WMScroller* WMGetScrollViewVerticalScroller(WMScrollView *sPtr);
|
||||||
|
|||||||
+1
-1
@@ -9,7 +9,7 @@ sk.po Slovak Jan 'judas' Tomka <judas@linux.sk>
|
|||||||
bg.po Bulgarian Anton Zinoviev <zinoviev@debian.org>
|
bg.po Bulgarian Anton Zinoviev <zinoviev@debian.org>
|
||||||
nl.po Dutch Alwin <translations@ziggo.nl>
|
nl.po Dutch Alwin <translations@ziggo.nl>
|
||||||
fy.po Frisian Alwin <translations@ziggo.nl>
|
fy.po Frisian Alwin <translations@ziggo.nl>
|
||||||
sr.po Serbian Strahinya Radich <contact@strahinja.org>
|
sr.po Serbian Strahinya Radich <sr@strahinja.org>
|
||||||
|
|
||||||
Notes
|
Notes
|
||||||
-----
|
-----
|
||||||
|
|||||||
+2
-2
@@ -3,7 +3,7 @@
|
|||||||
# 1998-2006 Dan Pascu
|
# 1998-2006 Dan Pascu
|
||||||
# 2013-2020 Window Maker Developers Team
|
# 2013-2020 Window Maker Developers Team
|
||||||
# This file is distributed under the same license as the Window Maker package.
|
# This file is distributed under the same license as the Window Maker package.
|
||||||
# Strahinya Radich (Страхиња Радић) <contact@strahinja.org>, 2023.
|
# Strahinya Radich (Страхиња Радић) <sr@strahinja.org>, 2023.
|
||||||
#
|
#
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -11,7 +11,7 @@ msgstr ""
|
|||||||
"Report-Msgid-Bugs-To: wmaker-dev@googlegroups.com\n"
|
"Report-Msgid-Bugs-To: wmaker-dev@googlegroups.com\n"
|
||||||
"POT-Creation-Date: 2023-11-02 19:36+0100\n"
|
"POT-Creation-Date: 2023-11-02 19:36+0100\n"
|
||||||
"PO-Revision-Date: 2023-11-02 19:48+0100\n"
|
"PO-Revision-Date: 2023-11-02 19:48+0100\n"
|
||||||
"Last-Translator: Страхиња Радић <contact@strahinja.org>\n"
|
"Last-Translator: Страхиња Радић <sr@strahinja.org>\n"
|
||||||
"Language-Team: Serbian <sr@li.org>\n"
|
"Language-Team: Serbian <sr@li.org>\n"
|
||||||
"Language: sr\n"
|
"Language: sr\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
|
|||||||
+37
-33
@@ -70,37 +70,30 @@ static Bool hasProperty(FcPattern * pattern, const char *property)
|
|||||||
return False;
|
return False;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Bool hasPropertyWithStringValue(FcPattern * pattern, const char *object, const char *value)
|
|
||||||
{
|
|
||||||
FcChar8 *str;
|
|
||||||
int id;
|
|
||||||
|
|
||||||
if (!value || value[0] == 0)
|
|
||||||
return True;
|
|
||||||
|
|
||||||
id = 0;
|
|
||||||
while (FcPatternGetString(pattern, object, id, &str) == FcResultMatch) {
|
|
||||||
if (strcasecmp(value, (char *)str) == 0) {
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
id++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
static char *makeFontOfSize(const char *font, int size, const char *fallback)
|
static char *makeFontOfSize(const char *font, int size, const char *fallback)
|
||||||
{
|
{
|
||||||
FcPattern *pattern;
|
FcPattern *pattern = NULL;
|
||||||
char *result;
|
char *result;
|
||||||
|
|
||||||
if (font[0] == '-') {
|
if (font && font[0] == '-') {
|
||||||
pattern = xlfdToFcPattern(font);
|
pattern = xlfdToFcPattern(font);
|
||||||
} else {
|
} else {
|
||||||
pattern = FcNameParse((const FcChar8 *) font);
|
pattern = FcNameParse((const FcChar8 *) font);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*FcPatternPrint(pattern); */
|
if (!pattern) {
|
||||||
|
wwarning(_("could not load font spec: %s."), font);
|
||||||
|
if (!fallback)
|
||||||
|
return NULL;
|
||||||
|
pattern = FcPatternCreate();
|
||||||
|
if (!pattern)
|
||||||
|
return NULL;
|
||||||
|
if (!FcPatternAddString(pattern, FC_FAMILY, (const FcChar8 *) fallback)) {
|
||||||
|
wfatal(_("could not load default font spec: %s."), fallback);
|
||||||
|
FcPatternDestroy(pattern);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (size > 0) {
|
if (size > 0) {
|
||||||
FcPatternDel(pattern, FC_PIXEL_SIZE);
|
FcPatternDel(pattern, FC_PIXEL_SIZE);
|
||||||
@@ -109,12 +102,6 @@ static char *makeFontOfSize(const char *font, int size, const char *fallback)
|
|||||||
FcPatternAddDouble(pattern, FC_PIXEL_SIZE, (double)DEFAULT_SIZE);
|
FcPatternAddDouble(pattern, FC_PIXEL_SIZE, (double)DEFAULT_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fallback && !hasPropertyWithStringValue(pattern, FC_FAMILY, fallback)) {
|
|
||||||
FcPatternAddString(pattern, FC_FAMILY, (const FcChar8 *) fallback);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*FcPatternPrint(pattern); */
|
|
||||||
|
|
||||||
result = (char *)FcNameUnparse(pattern);
|
result = (char *)FcNameUnparse(pattern);
|
||||||
FcPatternDestroy(pattern);
|
FcPatternDestroy(pattern);
|
||||||
|
|
||||||
@@ -135,7 +122,7 @@ WMFont *WMCreateFont(WMScreen * scrPtr, const char *fontName)
|
|||||||
double size;
|
double size;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (fontName[0] == '-') {
|
if (fontName && fontName[0] == '-') {
|
||||||
fname = xlfdToFcName(fontName);
|
fname = xlfdToFcName(fontName);
|
||||||
} else {
|
} else {
|
||||||
fname = wstrdup(fontName);
|
fname = wstrdup(fontName);
|
||||||
@@ -187,6 +174,10 @@ WMFont *WMCreateFont(WMScreen * scrPtr, const char *fontName)
|
|||||||
pango_layout_set_font_description(layout, description);
|
pango_layout_set_font_description(layout, description);
|
||||||
|
|
||||||
font->layout = layout;
|
font->layout = layout;
|
||||||
|
|
||||||
|
pango_font_description_free(description);
|
||||||
|
g_object_unref(context);
|
||||||
|
FcPatternDestroy(pattern);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
assert(WMHashInsert(scrPtr->fontCache, font->name, font) == NULL);
|
assert(WMHashInsert(scrPtr->fontCache, font->name, font) == NULL);
|
||||||
@@ -210,6 +201,11 @@ void WMReleaseFont(WMFont * font)
|
|||||||
font->refCount--;
|
font->refCount--;
|
||||||
if (font->refCount < 1) {
|
if (font->refCount < 1) {
|
||||||
XftFontClose(font->screen->display, font->font);
|
XftFontClose(font->screen->display, font->font);
|
||||||
|
#ifdef USE_PANGO
|
||||||
|
if (font->layout) {
|
||||||
|
g_object_unref(font->layout);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
if (font->name) {
|
if (font->name) {
|
||||||
WMHashRemove(font->screen->fontCache, font->name);
|
WMHashRemove(font->screen->fontCache, font->name);
|
||||||
wfree(font->name);
|
wfree(font->name);
|
||||||
@@ -262,7 +258,11 @@ WMFont *WMSystemFontOfSize(WMScreen * scrPtr, int size)
|
|||||||
WMFont *font;
|
WMFont *font;
|
||||||
char *fontSpec;
|
char *fontSpec;
|
||||||
|
|
||||||
fontSpec = makeFontOfSize(WINGsConfiguration.systemFont, size, NULL);
|
fontSpec = makeFontOfSize(WINGsConfiguration.systemFont, size, DEFAULT_FONT);
|
||||||
|
|
||||||
|
if (!fontSpec) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
font = WMCreateFont(scrPtr, fontSpec);
|
font = WMCreateFont(scrPtr, fontSpec);
|
||||||
|
|
||||||
@@ -280,7 +280,11 @@ WMFont *WMBoldSystemFontOfSize(WMScreen * scrPtr, int size)
|
|||||||
WMFont *font;
|
WMFont *font;
|
||||||
char *fontSpec;
|
char *fontSpec;
|
||||||
|
|
||||||
fontSpec = makeFontOfSize(WINGsConfiguration.boldSystemFont, size, NULL);
|
fontSpec = makeFontOfSize(WINGsConfiguration.boldSystemFont, size, DEFAULT_FONT);
|
||||||
|
|
||||||
|
if (!fontSpec) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
font = WMCreateFont(scrPtr, fontSpec);
|
font = WMCreateFont(scrPtr, fontSpec);
|
||||||
|
|
||||||
@@ -336,7 +340,7 @@ void WMDrawString(WMScreen * scr, Drawable d, WMColor * color, WMFont * font, in
|
|||||||
|
|
||||||
#ifdef USE_PANGO
|
#ifdef USE_PANGO
|
||||||
previous_text = pango_layout_get_text(font->layout);
|
previous_text = pango_layout_get_text(font->layout);
|
||||||
if ((previous_text == NULL) || (strcmp(text, previous_text) != 0))
|
if ((previous_text == NULL) || (strncmp(text, previous_text, length) != 0) || previous_text[length] != '\0')
|
||||||
pango_layout_set_text(font->layout, text, length);
|
pango_layout_set_text(font->layout, text, length);
|
||||||
pango_xft_render_layout(scr->xftdraw, &xftcolor, font->layout, x * PANGO_SCALE, y * PANGO_SCALE);
|
pango_xft_render_layout(scr->xftdraw, &xftcolor, font->layout, x * PANGO_SCALE, y * PANGO_SCALE);
|
||||||
#else
|
#else
|
||||||
@@ -374,7 +378,7 @@ WMDrawImageString(WMScreen * scr, Drawable d, WMColor * color, WMColor * backgro
|
|||||||
|
|
||||||
#ifdef USE_PANGO
|
#ifdef USE_PANGO
|
||||||
previous_text = pango_layout_get_text(font->layout);
|
previous_text = pango_layout_get_text(font->layout);
|
||||||
if ((previous_text == NULL) || (strcmp(text, previous_text) != 0))
|
if ((previous_text == NULL) || (strncmp(text, previous_text, length) != 0) || previous_text[length] != '\0')
|
||||||
pango_layout_set_text(font->layout, text, length);
|
pango_layout_set_text(font->layout, text, length);
|
||||||
pango_xft_render_layout(scr->xftdraw, &textColor, font->layout, x * PANGO_SCALE, y * PANGO_SCALE);
|
pango_xft_render_layout(scr->xftdraw, &textColor, font->layout, x * PANGO_SCALE, y * PANGO_SCALE);
|
||||||
#else
|
#else
|
||||||
|
|||||||
+498
-9
@@ -1,5 +1,7 @@
|
|||||||
|
|
||||||
#include "WINGsP.h"
|
#include "WINGsP.h"
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <strings.h>
|
||||||
|
|
||||||
const char *WMListDidScrollNotification = "WMListDidScrollNotification";
|
const char *WMListDidScrollNotification = "WMListDidScrollNotification";
|
||||||
const char *WMListSelectionDidChangeNotification = "WMListSelectionDidChangeNotification";
|
const char *WMListSelectionDidChangeNotification = "WMListSelectionDidChangeNotification";
|
||||||
@@ -27,11 +29,15 @@ typedef struct W_List {
|
|||||||
WMHandlerID *idleID; /* for updating the scroller after adding elements */
|
WMHandlerID *idleID; /* for updating the scroller after adding elements */
|
||||||
|
|
||||||
WMHandlerID *selectID; /* for selecting items in list while scrolling */
|
WMHandlerID *selectID; /* for selecting items in list while scrolling */
|
||||||
|
WMHandlerID *typeaheadID; /* for clearing typeahead buffer */
|
||||||
|
|
||||||
WMScroller *vScroller;
|
WMScroller *vScroller;
|
||||||
|
|
||||||
Pixmap doubleBuffer;
|
Pixmap doubleBuffer;
|
||||||
|
|
||||||
|
char *typeahead;
|
||||||
|
int typeaheadLen;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
unsigned int allowMultipleSelection:1;
|
unsigned int allowMultipleSelection:1;
|
||||||
unsigned int allowEmptySelection:1;
|
unsigned int allowEmptySelection:1;
|
||||||
@@ -48,6 +54,7 @@ typedef struct W_List {
|
|||||||
#define DEFAULT_HEIGHT 150
|
#define DEFAULT_HEIGHT 150
|
||||||
|
|
||||||
#define SCROLL_DELAY 100
|
#define SCROLL_DELAY 100
|
||||||
|
#define TYPEAHEAD_CLEAR_DELAY 700
|
||||||
|
|
||||||
static void destroyList(List * lPtr);
|
static void destroyList(List * lPtr);
|
||||||
static void paintList(List * lPtr);
|
static void paintList(List * lPtr);
|
||||||
@@ -62,6 +69,8 @@ static void scrollBackwardSelecting(void *data);
|
|||||||
static void vScrollCallBack(WMWidget * scroller, void *self);
|
static void vScrollCallBack(WMWidget * scroller, void *self);
|
||||||
|
|
||||||
static void toggleItemSelection(WMList * lPtr, int index);
|
static void toggleItemSelection(WMList * lPtr, int index);
|
||||||
|
static void jumpToFirstItemWithPrefix(WMList * lPtr, const char *prefix, int prefixLen);
|
||||||
|
static void typeaheadTimeout(void *data);
|
||||||
|
|
||||||
static void updateGeometry(WMList * lPtr);
|
static void updateGeometry(WMList * lPtr);
|
||||||
static void didResizeList(W_ViewDelegate * self, WMView * view);
|
static void didResizeList(W_ViewDelegate * self, WMView * view);
|
||||||
@@ -113,6 +122,9 @@ WMList *WMCreateList(WMWidget * parent)
|
|||||||
W_Screen *scrPtr = W_VIEW(parent)->screen;
|
W_Screen *scrPtr = W_VIEW(parent)->screen;
|
||||||
|
|
||||||
lPtr = wmalloc(sizeof(List));
|
lPtr = wmalloc(sizeof(List));
|
||||||
|
lPtr->typeahead = NULL;
|
||||||
|
lPtr->typeaheadLen = 0;
|
||||||
|
lPtr->typeaheadID = NULL;
|
||||||
|
|
||||||
lPtr->widgetClass = WC_List;
|
lPtr->widgetClass = WC_List;
|
||||||
|
|
||||||
@@ -129,7 +141,8 @@ WMList *WMCreateList(WMWidget * parent)
|
|||||||
| ClientMessageMask, handleEvents, lPtr);
|
| ClientMessageMask, handleEvents, lPtr);
|
||||||
|
|
||||||
WMCreateEventHandler(lPtr->view, ButtonPressMask | ButtonReleaseMask
|
WMCreateEventHandler(lPtr->view, ButtonPressMask | ButtonReleaseMask
|
||||||
| EnterWindowMask | LeaveWindowMask | ButtonMotionMask, handleActionEvents, lPtr);
|
| EnterWindowMask | LeaveWindowMask | ButtonMotionMask
|
||||||
|
| KeyPressMask, handleActionEvents, lPtr);
|
||||||
|
|
||||||
lPtr->itemHeight = WMFontHeight(scrPtr->normalFont) + 1;
|
lPtr->itemHeight = WMFontHeight(scrPtr->normalFont) + 1;
|
||||||
|
|
||||||
@@ -288,6 +301,14 @@ void WMClearList(WMList * lPtr)
|
|||||||
WMDeleteTimerHandler(lPtr->selectID);
|
WMDeleteTimerHandler(lPtr->selectID);
|
||||||
lPtr->selectID = NULL;
|
lPtr->selectID = NULL;
|
||||||
}
|
}
|
||||||
|
if (lPtr->typeaheadID) {
|
||||||
|
WMDeleteTimerHandler(lPtr->typeaheadID);
|
||||||
|
lPtr->typeaheadID = NULL;
|
||||||
|
}
|
||||||
|
if (lPtr->typeahead) {
|
||||||
|
lPtr->typeahead[0] = '\0';
|
||||||
|
lPtr->typeaheadLen = 0;
|
||||||
|
}
|
||||||
if (lPtr->view->flags.realized) {
|
if (lPtr->view->flags.realized) {
|
||||||
updateScroller(lPtr);
|
updateScroller(lPtr);
|
||||||
}
|
}
|
||||||
@@ -495,15 +516,16 @@ static void paintItem(List * lPtr, int index)
|
|||||||
static void paintList(List * lPtr)
|
static void paintList(List * lPtr)
|
||||||
{
|
{
|
||||||
W_Screen *scrPtr = lPtr->view->screen;
|
W_Screen *scrPtr = lPtr->view->screen;
|
||||||
int i, lim;
|
int i, lim, itemCount;
|
||||||
|
|
||||||
if (!lPtr->view->flags.mapped)
|
if (!lPtr->view->flags.mapped)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (WMGetArrayItemCount(lPtr->items) > 0) {
|
itemCount = WMGetArrayItemCount(lPtr->items);
|
||||||
if (lPtr->topItem + lPtr->fullFitLines + lPtr->flags.dontFitAll > WMGetArrayItemCount(lPtr->items)) {
|
if (itemCount > 0) {
|
||||||
|
if (lPtr->topItem + lPtr->fullFitLines + lPtr->flags.dontFitAll > itemCount) {
|
||||||
|
|
||||||
lim = WMGetArrayItemCount(lPtr->items) - lPtr->topItem;
|
lim = itemCount - lPtr->topItem;
|
||||||
XClearArea(scrPtr->display, lPtr->view->window, 19,
|
XClearArea(scrPtr->display, lPtr->view->window, 19,
|
||||||
2 + lim * lPtr->itemHeight, lPtr->view->size.width - 21,
|
2 + lim * lPtr->itemHeight, lPtr->view->size.width - 21,
|
||||||
lPtr->view->size.height - lim * lPtr->itemHeight - 3, False);
|
lPtr->view->size.height - lim * lPtr->itemHeight - 3, False);
|
||||||
@@ -820,7 +842,7 @@ void WMSetListSelectionToRange(WMList * lPtr, WMRange range)
|
|||||||
|
|
||||||
void WMSelectAllListItems(WMList * lPtr)
|
void WMSelectAllListItems(WMList * lPtr)
|
||||||
{
|
{
|
||||||
int i;
|
int i, itemCount;
|
||||||
WMListItem *item;
|
WMListItem *item;
|
||||||
|
|
||||||
if (!lPtr->flags.allowMultipleSelection)
|
if (!lPtr->flags.allowMultipleSelection)
|
||||||
@@ -833,7 +855,8 @@ void WMSelectAllListItems(WMList * lPtr)
|
|||||||
WMFreeArray(lPtr->selectedItems);
|
WMFreeArray(lPtr->selectedItems);
|
||||||
lPtr->selectedItems = WMCreateArrayWithArray(lPtr->items);
|
lPtr->selectedItems = WMCreateArrayWithArray(lPtr->items);
|
||||||
|
|
||||||
for (i = 0; i < WMGetArrayItemCount(lPtr->items); i++) {
|
itemCount = WMGetArrayItemCount(lPtr->items);
|
||||||
|
for (i = 0; i < itemCount; i++) {
|
||||||
item = WMGetFromArray(lPtr->items, i);
|
item = WMGetFromArray(lPtr->items, i);
|
||||||
if (!item->selected) {
|
if (!item->selected) {
|
||||||
item->selected = 1;
|
item->selected = 1;
|
||||||
@@ -859,10 +882,11 @@ void WMSelectAllListItems(WMList * lPtr)
|
|||||||
*/
|
*/
|
||||||
static void unselectAllListItems(WMList * lPtr, WMListItem * exceptThis)
|
static void unselectAllListItems(WMList * lPtr, WMListItem * exceptThis)
|
||||||
{
|
{
|
||||||
int i;
|
int i, itemCount;
|
||||||
WMListItem *item;
|
WMListItem *item;
|
||||||
|
|
||||||
for (i = 0; i < WMGetArrayItemCount(lPtr->items); i++) {
|
itemCount = WMGetArrayItemCount(lPtr->items);
|
||||||
|
for (i = 0; i < itemCount; i++) {
|
||||||
item = WMGetFromArray(lPtr->items, i);
|
item = WMGetFromArray(lPtr->items, i);
|
||||||
if (item != exceptThis && item->selected) {
|
if (item != exceptThis && item->selected) {
|
||||||
item->selected = 0;
|
item->selected = 0;
|
||||||
@@ -920,6 +944,85 @@ static void toggleItemSelection(WMList * lPtr, int index)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int findItemWithPrefix(List * lPtr, const char *prefix, int prefixLen)
|
||||||
|
{
|
||||||
|
if (prefixLen <= 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
int i, itemCount;
|
||||||
|
|
||||||
|
itemCount = WMGetArrayItemCount(lPtr->items);
|
||||||
|
for (i = 0; i < itemCount; i++) {
|
||||||
|
WMListItem *item = WMGetFromArray(lPtr->items, i);
|
||||||
|
|
||||||
|
if (!item || !item->text || item->text[0] == '\0')
|
||||||
|
continue;
|
||||||
|
if (strncasecmp(item->text, prefix, prefixLen) == 0)
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void jumpToFirstItemWithPrefix(WMList * lPtr, const char *prefix, int prefixLen)
|
||||||
|
{
|
||||||
|
int index, oldTop, visibleCount;
|
||||||
|
|
||||||
|
index = findItemWithPrefix(lPtr, prefix, prefixLen);
|
||||||
|
if (index < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (lPtr->flags.allowMultipleSelection) {
|
||||||
|
WMRange range;
|
||||||
|
|
||||||
|
range.position = index;
|
||||||
|
range.count = 1;
|
||||||
|
WMSetListSelectionToRange(lPtr, range);
|
||||||
|
} else {
|
||||||
|
WMSelectListItem(lPtr, index);
|
||||||
|
/* Trigger action callback */
|
||||||
|
if (lPtr->action)
|
||||||
|
(*lPtr->action) (lPtr, lPtr->clientData);
|
||||||
|
}
|
||||||
|
|
||||||
|
visibleCount = lPtr->fullFitLines + lPtr->flags.dontFitAll;
|
||||||
|
if (visibleCount < 1)
|
||||||
|
visibleCount = 1;
|
||||||
|
|
||||||
|
oldTop = lPtr->topItem;
|
||||||
|
if (index < lPtr->topItem) {
|
||||||
|
lPtr->topItem = index;
|
||||||
|
} else {
|
||||||
|
if (lPtr->flags.dontFitAll) {
|
||||||
|
if (lPtr->fullFitLines <= 0) {
|
||||||
|
lPtr->topItem = index;
|
||||||
|
} else {
|
||||||
|
int lastFullyVisible = lPtr->topItem + lPtr->fullFitLines - 1;
|
||||||
|
if (index > lastFullyVisible)
|
||||||
|
lPtr->topItem = index - lPtr->fullFitLines + 1;
|
||||||
|
}
|
||||||
|
} else if (index >= lPtr->topItem + visibleCount) {
|
||||||
|
lPtr->topItem = index - visibleCount + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (lPtr->topItem < 0)
|
||||||
|
lPtr->topItem = 0;
|
||||||
|
|
||||||
|
if (lPtr->view->flags.realized && lPtr->topItem != oldTop)
|
||||||
|
updateScroller(lPtr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void typeaheadTimeout(void *data)
|
||||||
|
{
|
||||||
|
List *lPtr = (List *) data;
|
||||||
|
|
||||||
|
lPtr->typeaheadID = NULL;
|
||||||
|
if (lPtr->typeahead) {
|
||||||
|
lPtr->typeahead[0] = '\0';
|
||||||
|
lPtr->typeaheadLen = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void handleActionEvents(XEvent * event, void *data)
|
static void handleActionEvents(XEvent * event, void *data)
|
||||||
{
|
{
|
||||||
List *lPtr = (List *) data;
|
List *lPtr = (List *) data;
|
||||||
@@ -959,6 +1062,7 @@ static void handleActionEvents(XEvent * event, void *data)
|
|||||||
WMDeleteTimerHandler(lPtr->selectID);
|
WMDeleteTimerHandler(lPtr->selectID);
|
||||||
lPtr->selectID = NULL;
|
lPtr->selectID = NULL;
|
||||||
}
|
}
|
||||||
|
WMSetFocusToWidget(lPtr);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LeaveNotify:
|
case LeaveNotify:
|
||||||
@@ -970,6 +1074,9 @@ static void handleActionEvents(XEvent * event, void *data)
|
|||||||
lPtr->selectID = WMAddTimerHandler(SCROLL_DELAY, scrollBackwardSelecting, lPtr);
|
lPtr->selectID = WMAddTimerHandler(SCROLL_DELAY, scrollBackwardSelecting, lPtr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
WMWidget *parentWidget = WMWidgetOfView(lPtr->view->parent);
|
||||||
|
if (parentWidget)
|
||||||
|
WMSetFocusToWidget(parentWidget);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ButtonPress:
|
case ButtonPress:
|
||||||
@@ -1076,6 +1183,381 @@ static void handleActionEvents(XEvent * event, void *data)
|
|||||||
prevItem = tmp;
|
prevItem = tmp;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case KeyPress:
|
||||||
|
char buffer[16];
|
||||||
|
KeySym ksym;
|
||||||
|
Status status;
|
||||||
|
int len;
|
||||||
|
WMScreen *scr = lPtr->view->screen;
|
||||||
|
XWindowAttributes wattr;
|
||||||
|
|
||||||
|
if (event->xkey.state & (ControlMask | Mod1Mask))
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (!(XGetWindowAttributes(scr->display, lPtr->view->window, &wattr) && wattr.map_state == IsViewable))
|
||||||
|
break;
|
||||||
|
|
||||||
|
len = W_LookupString(lPtr->view, &event->xkey, buffer, (int)sizeof(buffer) - 1, &ksym, &status);
|
||||||
|
if (len < 0)
|
||||||
|
break;
|
||||||
|
if (len > 0)
|
||||||
|
buffer[len] = '\0';
|
||||||
|
|
||||||
|
/* Handle navigation keys */
|
||||||
|
switch (ksym) {
|
||||||
|
case XK_Up: {
|
||||||
|
int newRow;
|
||||||
|
int itemCount = WMGetArrayItemCount(lPtr->items);
|
||||||
|
int cur = WMGetListSelectedItemRow(lPtr);
|
||||||
|
|
||||||
|
if (lPtr->flags.allowMultipleSelection && WMGetArrayItemCount(lPtr->selectedItems) > 0) {
|
||||||
|
WMListItem *lastSel = WMGetFromArray(lPtr->selectedItems, WMGetArrayItemCount(lPtr->selectedItems) - 1);
|
||||||
|
if (lastSel)
|
||||||
|
cur = WMGetFirstInArray(lPtr->items, lastSel);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cur == WLNotFound)
|
||||||
|
cur = lPtr->topItem;
|
||||||
|
newRow = cur - 1;
|
||||||
|
if (newRow < 0)
|
||||||
|
newRow = 0;
|
||||||
|
|
||||||
|
if (newRow != cur && itemCount > 0) {
|
||||||
|
if (lPtr->flags.allowMultipleSelection) {
|
||||||
|
if (event->xkey.state & ShiftMask) {
|
||||||
|
WMRange range;
|
||||||
|
int anchor = WMGetListSelectedItemRow(lPtr);
|
||||||
|
if (anchor == WLNotFound || WMGetArrayItemCount(lPtr->selectedItems) == 0) {
|
||||||
|
anchor = cur;
|
||||||
|
}
|
||||||
|
|
||||||
|
range.position = anchor;
|
||||||
|
if (newRow >= anchor)
|
||||||
|
range.count = newRow - anchor + 1;
|
||||||
|
else
|
||||||
|
range.count = newRow - anchor - 1;
|
||||||
|
WMSetListSelectionToRange(lPtr, range);
|
||||||
|
} else {
|
||||||
|
WMRange range = { .position = newRow, .count = 1 };
|
||||||
|
WMSetListSelectionToRange(lPtr, range);
|
||||||
|
lastClicked = newRow;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
WMSelectListItem(lPtr, newRow);
|
||||||
|
lastClicked = newRow;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ensure visibility */
|
||||||
|
if (newRow < lPtr->topItem) {
|
||||||
|
lPtr->topItem = newRow;
|
||||||
|
if (lPtr->view->flags.realized)
|
||||||
|
updateScroller(lPtr);
|
||||||
|
}
|
||||||
|
/* Trigger action callback */
|
||||||
|
if (lPtr->action)
|
||||||
|
(*lPtr->action) (lPtr, lPtr->clientData);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case XK_Down: {
|
||||||
|
int newRow;
|
||||||
|
int itemCount = WMGetArrayItemCount(lPtr->items);
|
||||||
|
int cur = WMGetListSelectedItemRow(lPtr);
|
||||||
|
|
||||||
|
if (lPtr->flags.allowMultipleSelection && WMGetArrayItemCount(lPtr->selectedItems) > 0) {
|
||||||
|
WMListItem *lastSel = WMGetFromArray(lPtr->selectedItems, WMGetArrayItemCount(lPtr->selectedItems) - 1);
|
||||||
|
if (lastSel)
|
||||||
|
cur = WMGetFirstInArray(lPtr->items, lastSel);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cur == WLNotFound)
|
||||||
|
cur = lPtr->topItem;
|
||||||
|
newRow = cur + 1;
|
||||||
|
if (newRow >= itemCount)
|
||||||
|
newRow = itemCount - 1;
|
||||||
|
|
||||||
|
if (newRow != cur && itemCount > 0) {
|
||||||
|
if (lPtr->flags.allowMultipleSelection) {
|
||||||
|
if (event->xkey.state & ShiftMask) {
|
||||||
|
WMRange range;
|
||||||
|
int anchor = WMGetListSelectedItemRow(lPtr);
|
||||||
|
if (anchor == WLNotFound || WMGetArrayItemCount(lPtr->selectedItems) == 0) {
|
||||||
|
anchor = cur;
|
||||||
|
}
|
||||||
|
|
||||||
|
range.position = anchor;
|
||||||
|
if (newRow >= anchor)
|
||||||
|
range.count = newRow - anchor + 1;
|
||||||
|
else
|
||||||
|
range.count = newRow - anchor - 1;
|
||||||
|
WMSetListSelectionToRange(lPtr, range);
|
||||||
|
} else {
|
||||||
|
WMRange range = { .position = newRow, .count = 1 };
|
||||||
|
WMSetListSelectionToRange(lPtr, range);
|
||||||
|
lastClicked = newRow;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
WMSelectListItem(lPtr, newRow);
|
||||||
|
lastClicked = newRow;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ensure visibility */
|
||||||
|
if (newRow > (lPtr->topItem + lPtr->fullFitLines - 1)) {
|
||||||
|
lPtr->topItem = newRow - lPtr->fullFitLines + 1;
|
||||||
|
if (lPtr->topItem < 0)
|
||||||
|
lPtr->topItem = 0;
|
||||||
|
/* Ensure we don't scroll past the end */
|
||||||
|
if (lPtr->topItem + lPtr->fullFitLines > itemCount)
|
||||||
|
lPtr->topItem = itemCount - lPtr->fullFitLines;
|
||||||
|
if (lPtr->topItem < 0)
|
||||||
|
lPtr->topItem = 0;
|
||||||
|
if (lPtr->view->flags.realized)
|
||||||
|
updateScroller(lPtr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Trigger action callback */
|
||||||
|
if (lPtr->action)
|
||||||
|
(*lPtr->action) (lPtr, lPtr->clientData);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case XK_Page_Up: {
|
||||||
|
int newRow;
|
||||||
|
int page = lPtr->fullFitLines > 0 ? lPtr->fullFitLines : 1;
|
||||||
|
int cur = WMGetListSelectedItemRow(lPtr);
|
||||||
|
|
||||||
|
if (cur == WLNotFound)
|
||||||
|
cur = lPtr->topItem;
|
||||||
|
newRow = cur - page;
|
||||||
|
if (newRow < 0)
|
||||||
|
newRow = 0;
|
||||||
|
|
||||||
|
if (newRow != cur) {
|
||||||
|
if (lPtr->flags.allowMultipleSelection) {
|
||||||
|
if (event->xkey.state & ShiftMask) {
|
||||||
|
WMRange range;
|
||||||
|
int anchor = WMGetListSelectedItemRow(lPtr);
|
||||||
|
if (anchor == WLNotFound || WMGetArrayItemCount(lPtr->selectedItems) == 0) {
|
||||||
|
anchor = cur;
|
||||||
|
}
|
||||||
|
|
||||||
|
range.position = anchor;
|
||||||
|
if (newRow >= anchor)
|
||||||
|
range.count = newRow - anchor + 1;
|
||||||
|
else
|
||||||
|
range.count = newRow - anchor - 1;
|
||||||
|
WMSetListSelectionToRange(lPtr, range);
|
||||||
|
} else {
|
||||||
|
WMRange range = { .position = newRow, .count = 1 };
|
||||||
|
WMSetListSelectionToRange(lPtr, range);
|
||||||
|
lastClicked = newRow;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
WMSelectListItem(lPtr, newRow);
|
||||||
|
lastClicked = newRow;
|
||||||
|
}
|
||||||
|
if (newRow < lPtr->topItem) {
|
||||||
|
lPtr->topItem = newRow;
|
||||||
|
if (lPtr->view->flags.realized)
|
||||||
|
updateScroller(lPtr);
|
||||||
|
}
|
||||||
|
/* Trigger action callback */
|
||||||
|
if (lPtr->action)
|
||||||
|
(*lPtr->action) (lPtr, lPtr->clientData);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case XK_Page_Down: {
|
||||||
|
int newRow;
|
||||||
|
int page = lPtr->fullFitLines > 0 ? lPtr->fullFitLines : 1;
|
||||||
|
int itemCount = WMGetArrayItemCount(lPtr->items);
|
||||||
|
int cur = WMGetListSelectedItemRow(lPtr);
|
||||||
|
|
||||||
|
if (cur == WLNotFound)
|
||||||
|
cur = lPtr->topItem;
|
||||||
|
newRow = cur + page;
|
||||||
|
if (newRow >= itemCount)
|
||||||
|
newRow = itemCount - 1;
|
||||||
|
|
||||||
|
if (newRow != cur && itemCount > 0) {
|
||||||
|
if (lPtr->flags.allowMultipleSelection) {
|
||||||
|
if (event->xkey.state & ShiftMask) {
|
||||||
|
WMRange range;
|
||||||
|
int anchor = WMGetListSelectedItemRow(lPtr);
|
||||||
|
if (anchor == WLNotFound || WMGetArrayItemCount(lPtr->selectedItems) == 0) {
|
||||||
|
anchor = cur;
|
||||||
|
}
|
||||||
|
|
||||||
|
range.position = anchor;
|
||||||
|
if (newRow >= anchor)
|
||||||
|
range.count = newRow - anchor + 1;
|
||||||
|
else
|
||||||
|
range.count = newRow - anchor - 1;
|
||||||
|
WMSetListSelectionToRange(lPtr, range);
|
||||||
|
} else {
|
||||||
|
WMRange range = { .position = newRow, .count = 1 };
|
||||||
|
WMSetListSelectionToRange(lPtr, range);
|
||||||
|
lastClicked = newRow;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
WMSelectListItem(lPtr, newRow);
|
||||||
|
lastClicked = newRow;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ensure visibility */
|
||||||
|
if (newRow > (lPtr->topItem + lPtr->fullFitLines - 1)) {
|
||||||
|
lPtr->topItem = newRow - lPtr->fullFitLines + 1;
|
||||||
|
if (lPtr->topItem < 0)
|
||||||
|
lPtr->topItem = 0;
|
||||||
|
/* Ensure we don't scroll past the end */
|
||||||
|
if (lPtr->topItem + lPtr->fullFitLines > itemCount)
|
||||||
|
lPtr->topItem = itemCount - lPtr->fullFitLines;
|
||||||
|
if (lPtr->topItem < 0)
|
||||||
|
lPtr->topItem = 0;
|
||||||
|
if (lPtr->view->flags.realized)
|
||||||
|
updateScroller(lPtr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Trigger action callback */
|
||||||
|
if (lPtr->action)
|
||||||
|
(*lPtr->action) (lPtr, lPtr->clientData);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case XK_Home: {
|
||||||
|
int itemCount = WMGetArrayItemCount(lPtr->items);
|
||||||
|
if (itemCount > 0) {
|
||||||
|
int newRow = 0;
|
||||||
|
if (lPtr->flags.allowMultipleSelection) {
|
||||||
|
if (event->xkey.state & ShiftMask) {
|
||||||
|
WMRange range;
|
||||||
|
int anchor = WMGetListSelectedItemRow(lPtr);
|
||||||
|
if (anchor == WLNotFound || WMGetArrayItemCount(lPtr->selectedItems) == 0) {
|
||||||
|
anchor = lPtr->topItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
range.position = anchor;
|
||||||
|
if (newRow >= anchor)
|
||||||
|
range.count = newRow - anchor + 1;
|
||||||
|
else
|
||||||
|
range.count = newRow - anchor - 1;
|
||||||
|
WMSetListSelectionToRange(lPtr, range);
|
||||||
|
} else {
|
||||||
|
WMRange range = { .position = newRow, .count = 1 };
|
||||||
|
WMSetListSelectionToRange(lPtr, range);
|
||||||
|
lastClicked = newRow;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
WMSelectListItem(lPtr, newRow);
|
||||||
|
lastClicked = newRow;
|
||||||
|
}
|
||||||
|
if (newRow < lPtr->topItem) {
|
||||||
|
lPtr->topItem = newRow;
|
||||||
|
if (lPtr->view->flags.realized)
|
||||||
|
updateScroller(lPtr);
|
||||||
|
}
|
||||||
|
/* Trigger action callback */
|
||||||
|
if (lPtr->action)
|
||||||
|
(*lPtr->action) (lPtr, lPtr->clientData);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case XK_End: {
|
||||||
|
int itemCount = WMGetArrayItemCount(lPtr->items);
|
||||||
|
if (itemCount > 0) {
|
||||||
|
int newRow = itemCount - 1;
|
||||||
|
if (lPtr->flags.allowMultipleSelection) {
|
||||||
|
if (event->xkey.state & ShiftMask) {
|
||||||
|
WMRange range;
|
||||||
|
int anchor = WMGetListSelectedItemRow(lPtr);
|
||||||
|
if (anchor == WLNotFound || WMGetArrayItemCount(lPtr->selectedItems) == 0) {
|
||||||
|
anchor = lPtr->topItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
range.position = anchor;
|
||||||
|
if (newRow >= anchor)
|
||||||
|
range.count = newRow - anchor + 1;
|
||||||
|
else
|
||||||
|
range.count = newRow - anchor - 1;
|
||||||
|
WMSetListSelectionToRange(lPtr, range);
|
||||||
|
} else {
|
||||||
|
WMRange range = { .position = newRow, .count = 1 };
|
||||||
|
WMSetListSelectionToRange(lPtr, range);
|
||||||
|
lastClicked = newRow;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
WMSelectListItem(lPtr, newRow);
|
||||||
|
lastClicked = newRow;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ensure the last item is fully visible */
|
||||||
|
lPtr->topItem = itemCount - lPtr->fullFitLines;
|
||||||
|
if (lPtr->topItem < 0)
|
||||||
|
lPtr->topItem = 0;
|
||||||
|
if (lPtr->view->flags.realized)
|
||||||
|
updateScroller(lPtr);
|
||||||
|
|
||||||
|
/* Trigger action callback */
|
||||||
|
if (lPtr->action)
|
||||||
|
(*lPtr->action) (lPtr, lPtr->clientData);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we handled a navigation keysym, avoid falling through to typeahead logic */
|
||||||
|
if (ksym == XK_Up || ksym == XK_Down || ksym == XK_Page_Up || ksym == XK_Page_Down || ksym == XK_Home || ksym == XK_End)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (len <= 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
buffer[len] = '\0';
|
||||||
|
|
||||||
|
if (ksym == XK_Escape) {
|
||||||
|
if (lPtr->typeaheadID) {
|
||||||
|
WMDeleteTimerHandler(lPtr->typeaheadID);
|
||||||
|
lPtr->typeaheadID = NULL;
|
||||||
|
}
|
||||||
|
if (lPtr->typeahead) {
|
||||||
|
lPtr->typeahead[0] = '\0';
|
||||||
|
lPtr->typeaheadLen = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ksym == XK_BackSpace) {
|
||||||
|
if (lPtr->typeaheadLen > 0 && lPtr->typeahead) {
|
||||||
|
lPtr->typeaheadLen--;
|
||||||
|
lPtr->typeahead[lPtr->typeaheadLen] = '\0';
|
||||||
|
}
|
||||||
|
} else if (len == 1 && isalnum((unsigned char)buffer[0])) {
|
||||||
|
if (!lPtr->typeahead) {
|
||||||
|
lPtr->typeahead = wmalloc(2);
|
||||||
|
lPtr->typeaheadLen = 0;
|
||||||
|
}
|
||||||
|
lPtr->typeahead = wrealloc(lPtr->typeahead, lPtr->typeaheadLen + 2);
|
||||||
|
lPtr->typeahead[lPtr->typeaheadLen] = buffer[0];
|
||||||
|
lPtr->typeaheadLen++;
|
||||||
|
lPtr->typeahead[lPtr->typeaheadLen] = '\0';
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lPtr->typeaheadLen > 0)
|
||||||
|
jumpToFirstItemWithPrefix(lPtr, lPtr->typeahead, lPtr->typeaheadLen);
|
||||||
|
|
||||||
|
if (lPtr->typeaheadID) {
|
||||||
|
WMDeleteTimerHandler(lPtr->typeaheadID);
|
||||||
|
lPtr->typeaheadID = NULL;
|
||||||
|
}
|
||||||
|
if (lPtr->typeaheadLen > 0)
|
||||||
|
lPtr->typeaheadID = WMAddTimerHandler(TYPEAHEAD_CLEAR_DELAY, typeaheadTimeout, lPtr);
|
||||||
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
if (lPtr->topItem != topItem)
|
if (lPtr->topItem != topItem)
|
||||||
WMPostNotificationName(WMListDidScrollNotification, lPtr, NULL);
|
WMPostNotificationName(WMListDidScrollNotification, lPtr, NULL);
|
||||||
@@ -1123,6 +1605,10 @@ static void destroyList(List * lPtr)
|
|||||||
WMDeleteTimerHandler(lPtr->selectID);
|
WMDeleteTimerHandler(lPtr->selectID);
|
||||||
lPtr->selectID = NULL;
|
lPtr->selectID = NULL;
|
||||||
|
|
||||||
|
if (lPtr->typeaheadID)
|
||||||
|
WMDeleteTimerHandler(lPtr->typeaheadID);
|
||||||
|
lPtr->typeaheadID = NULL;
|
||||||
|
|
||||||
if (lPtr->selectedItems)
|
if (lPtr->selectedItems)
|
||||||
WMFreeArray(lPtr->selectedItems);
|
WMFreeArray(lPtr->selectedItems);
|
||||||
|
|
||||||
@@ -1132,6 +1618,9 @@ static void destroyList(List * lPtr)
|
|||||||
if (lPtr->doubleBuffer)
|
if (lPtr->doubleBuffer)
|
||||||
XFreePixmap(lPtr->view->screen->display, lPtr->doubleBuffer);
|
XFreePixmap(lPtr->view->screen->display, lPtr->doubleBuffer);
|
||||||
|
|
||||||
|
if (lPtr->typeahead)
|
||||||
|
wfree(lPtr->typeahead);
|
||||||
|
|
||||||
WMRemoveNotificationObserver(lPtr);
|
WMRemoveNotificationObserver(lPtr);
|
||||||
|
|
||||||
wfree(lPtr);
|
wfree(lPtr);
|
||||||
|
|||||||
@@ -252,6 +252,56 @@ WMMenuItem *WMGetPopUpButtonMenuItem(WMPopUpButton * bPtr, int index)
|
|||||||
return WMGetFromArray(bPtr->items, index);
|
return WMGetFromArray(bPtr->items, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int WMSelectPopUpButtonPreviousItem(WMPopUpButton * bPtr)
|
||||||
|
{
|
||||||
|
int testIndex;
|
||||||
|
|
||||||
|
CHECK_CLASS(bPtr, WC_PopUpButton);
|
||||||
|
|
||||||
|
if (bPtr->flags.pullsDown || bPtr->selectedItemIndex < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
testIndex = bPtr->selectedItemIndex - 1;
|
||||||
|
|
||||||
|
while (testIndex >= 0 && !WMGetPopUpButtonItemEnabled(bPtr, testIndex))
|
||||||
|
testIndex--;
|
||||||
|
|
||||||
|
if (testIndex != -1) {
|
||||||
|
WMSetPopUpButtonSelectedItem(bPtr, testIndex);
|
||||||
|
if (bPtr->action)
|
||||||
|
(*bPtr->action) (bPtr, bPtr->clientData);
|
||||||
|
return testIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int WMSelectPopUpButtonNextItem(WMPopUpButton * bPtr)
|
||||||
|
{
|
||||||
|
int itemCount;
|
||||||
|
int testIndex;
|
||||||
|
|
||||||
|
CHECK_CLASS(bPtr, WC_PopUpButton);
|
||||||
|
|
||||||
|
if (bPtr->flags.pullsDown || bPtr->selectedItemIndex < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
itemCount = WMGetArrayItemCount(bPtr->items);
|
||||||
|
testIndex = bPtr->selectedItemIndex + 1;
|
||||||
|
|
||||||
|
while (testIndex < itemCount && !WMGetPopUpButtonItemEnabled(bPtr, testIndex))
|
||||||
|
testIndex++;
|
||||||
|
|
||||||
|
if (testIndex != itemCount) {
|
||||||
|
WMSetPopUpButtonSelectedItem(bPtr, testIndex);
|
||||||
|
if (bPtr->action)
|
||||||
|
(*bPtr->action) (bPtr, bPtr->clientData);
|
||||||
|
return testIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
static void paintPopUpButton(PopUpButton * bPtr)
|
static void paintPopUpButton(PopUpButton * bPtr)
|
||||||
{
|
{
|
||||||
W_Screen *scr = bPtr->view->screen;
|
W_Screen *scr = bPtr->view->screen;
|
||||||
|
|||||||
+16
-16
@@ -219,9 +219,9 @@ static char *default_bullet[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* These id are used when sharing the selected text between applications */
|
/* These id are used when sharing the selected text between applications */
|
||||||
static Atom XA_Targets = None;
|
static Atom XA_TARGETS = None;
|
||||||
static Atom XA_Format_Text = None;
|
static Atom XA_TEXT = None;
|
||||||
static Atom XA_Format_Compound_Text = None;
|
static Atom XA_COMPOUND_TEXT = None;
|
||||||
|
|
||||||
static void handleEvents(XEvent * event, void *data);
|
static void handleEvents(XEvent * event, void *data);
|
||||||
static void layOutDocument(Text * tPtr);
|
static void layOutDocument(Text * tPtr);
|
||||||
@@ -2050,7 +2050,7 @@ static WMData *requestHandler(WMView * view, Atom selection, Atom target, void *
|
|||||||
(void) selection;
|
(void) selection;
|
||||||
(void) cdata;
|
(void) cdata;
|
||||||
|
|
||||||
if (target == XA_STRING || target == XA_Format_Text || target == XA_Format_Compound_Text) {
|
if (target == XA_STRING || target == XA_TEXT || target == XA_COMPOUND_TEXT) {
|
||||||
char *text = WMGetTextSelectedStream(tPtr);
|
char *text = WMGetTextSelectedStream(tPtr);
|
||||||
|
|
||||||
if (text) {
|
if (text) {
|
||||||
@@ -2063,18 +2063,18 @@ static WMData *requestHandler(WMView * view, Atom selection, Atom target, void *
|
|||||||
} else
|
} else
|
||||||
printf("didn't get it\n");
|
printf("didn't get it\n");
|
||||||
|
|
||||||
if (target == XA_Targets) {
|
if (target == XA_TARGETS) {
|
||||||
Atom array[4];
|
Atom supported_type[4];
|
||||||
|
|
||||||
array[0] = XA_Targets;
|
supported_type[0] = XA_TARGETS;
|
||||||
array[1] = XA_STRING;
|
supported_type[1] = XA_STRING;
|
||||||
array[2] = XA_Format_Text;
|
supported_type[2] = XA_TEXT;
|
||||||
array[3] = XA_Format_Compound_Text;
|
supported_type[3] = XA_COMPOUND_TEXT;
|
||||||
|
|
||||||
data = WMCreateDataWithBytes(&array, sizeof(array));
|
data = WMCreateDataWithBytes(supported_type, sizeof(supported_type));
|
||||||
WMSetDataFormat(data, 32);
|
WMSetDataFormat(data, 32);
|
||||||
|
|
||||||
*type = target;
|
*type = XA_ATOM;
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2977,15 +2977,15 @@ WMText *WMCreateTextForDocumentType(WMWidget * parent, WMAction * parser, WMActi
|
|||||||
dpy = tPtr->view->screen->display;
|
dpy = tPtr->view->screen->display;
|
||||||
scr = tPtr->view->screen;
|
scr = tPtr->view->screen;
|
||||||
|
|
||||||
if (XA_Targets == None) {
|
if (XA_TARGETS == None) {
|
||||||
/*
|
/*
|
||||||
* Because the X protocol guaranties that the value will never change in
|
* Because the X protocol guaranties that the value will never change in
|
||||||
* the lifespan of the server, we query the values only the first time a
|
* the lifespan of the server, we query the values only the first time a
|
||||||
* widget is created
|
* widget is created
|
||||||
*/
|
*/
|
||||||
XA_Targets = XInternAtom(dpy, "TARGETS", False);
|
XA_TARGETS = XInternAtom(dpy, "TARGETS", False);
|
||||||
XA_Format_Text = XInternAtom(dpy, "TEXT", False);
|
XA_TEXT = XInternAtom(dpy, "TEXT", False);
|
||||||
XA_Format_Compound_Text = XInternAtom(dpy, "COMPOUND_TEXT", False);
|
XA_COMPOUND_TEXT = XInternAtom(dpy, "COMPOUND_TEXT", False);
|
||||||
}
|
}
|
||||||
|
|
||||||
tPtr->view->self = tPtr;
|
tPtr->view->self = tPtr;
|
||||||
|
|||||||
+89
-59
@@ -239,9 +239,9 @@ static WMData *requestHandler(WMView * view, Atom selection, Atom target, void *
|
|||||||
TextField *tPtr = view->self;
|
TextField *tPtr = view->self;
|
||||||
int count;
|
int count;
|
||||||
Display *dpy = tPtr->view->screen->display;
|
Display *dpy = tPtr->view->screen->display;
|
||||||
Atom _TARGETS;
|
Atom XA_TARGETS;
|
||||||
Atom TEXT = XInternAtom(dpy, "TEXT", False);
|
Atom XA_TEXT = XInternAtom(dpy, "TEXT", False);
|
||||||
Atom COMPOUND_TEXT = XInternAtom(dpy, "COMPOUND_TEXT", False);
|
Atom XA_COMPOUND_TEXT = XInternAtom(dpy, "COMPOUND_TEXT", False);
|
||||||
WMData *data;
|
WMData *data;
|
||||||
|
|
||||||
/* Parameter not used, but tell the compiler that it is ok */
|
/* Parameter not used, but tell the compiler that it is ok */
|
||||||
@@ -251,7 +251,7 @@ static WMData *requestHandler(WMView * view, Atom selection, Atom target, void *
|
|||||||
count = tPtr->selection.count < 0
|
count = tPtr->selection.count < 0
|
||||||
? tPtr->selection.position + tPtr->selection.count : tPtr->selection.position;
|
? tPtr->selection.position + tPtr->selection.count : tPtr->selection.position;
|
||||||
|
|
||||||
if (target == XA_STRING || target == TEXT || target == COMPOUND_TEXT) {
|
if (target == XA_STRING || target == XA_TEXT || target == XA_COMPOUND_TEXT) {
|
||||||
|
|
||||||
data = WMCreateDataWithBytes(&(tPtr->text[count]), abs(tPtr->selection.count));
|
data = WMCreateDataWithBytes(&(tPtr->text[count]), abs(tPtr->selection.count));
|
||||||
WMSetDataFormat(data, 8);
|
WMSetDataFormat(data, 8);
|
||||||
@@ -260,19 +260,19 @@ static WMData *requestHandler(WMView * view, Atom selection, Atom target, void *
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
_TARGETS = XInternAtom(dpy, "TARGETS", False);
|
XA_TARGETS = XInternAtom(dpy, "TARGETS", False);
|
||||||
if (target == _TARGETS) {
|
if (target == XA_TARGETS) {
|
||||||
Atom supported_type[4];
|
Atom supported_type[4];
|
||||||
|
|
||||||
supported_type[0] = _TARGETS;
|
supported_type[0] = XA_TARGETS;
|
||||||
supported_type[1] = XA_STRING;
|
supported_type[1] = XA_STRING;
|
||||||
supported_type[2] = TEXT;
|
supported_type[2] = XA_TEXT;
|
||||||
supported_type[3] = COMPOUND_TEXT;
|
supported_type[3] = XA_COMPOUND_TEXT;
|
||||||
|
|
||||||
data = WMCreateDataWithBytes(supported_type, sizeof(supported_type));
|
data = WMCreateDataWithBytes(supported_type, sizeof(supported_type));
|
||||||
WMSetDataFormat(data, 32);
|
WMSetDataFormat(data, 32);
|
||||||
|
|
||||||
*type = target;
|
*type = XA_ATOM;
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -446,6 +446,13 @@ void WMDeleteTextFieldRange(WMTextField * tPtr, WMRange range)
|
|||||||
|
|
||||||
decrToFit(tPtr);
|
decrToFit(tPtr);
|
||||||
|
|
||||||
|
/* Ensure cursor is visible after deletion */
|
||||||
|
if (tPtr->cursorPosition < tPtr->viewPosition) {
|
||||||
|
tPtr->viewPosition = tPtr->cursorPosition;
|
||||||
|
} else {
|
||||||
|
incrToFit2(tPtr);
|
||||||
|
}
|
||||||
|
|
||||||
paintTextField(tPtr);
|
paintTextField(tPtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -490,11 +497,6 @@ void WMSetTextFieldAlignment(WMTextField * tPtr, WMAlignment alignment)
|
|||||||
|
|
||||||
tPtr->flags.alignment = alignment;
|
tPtr->flags.alignment = alignment;
|
||||||
|
|
||||||
if (alignment != WALeft) {
|
|
||||||
wwarning(_("only left alignment is supported in textfields"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tPtr->view->flags.realized) {
|
if (tPtr->view->flags.realized) {
|
||||||
paintTextField(tPtr);
|
paintTextField(tPtr);
|
||||||
}
|
}
|
||||||
@@ -846,8 +848,8 @@ static void paintTextField(TextField * tPtr)
|
|||||||
count = tPtr->viewPosition;
|
count = tPtr->viewPosition;
|
||||||
}
|
}
|
||||||
|
|
||||||
rx = tPtr->offsetWidth + 1 + WMWidthOfString(tPtr->font, text, count)
|
rx = tx + WMWidthOfString(tPtr->font, &(text[tPtr->viewPosition]),
|
||||||
- WMWidthOfString(tPtr->font, text, tPtr->viewPosition);
|
count - tPtr->viewPosition);
|
||||||
|
|
||||||
WMDrawImageString(screen, drawbuffer, color, screen->gray,
|
WMDrawImageString(screen, drawbuffer, color, screen->gray,
|
||||||
tPtr->font, rx, ty, &(text[count]), count2);
|
tPtr->font, rx, ty, &(text[count]), count2);
|
||||||
@@ -1029,7 +1031,6 @@ static void handleTextFieldKeyPress(TextField * tPtr, XEvent * event)
|
|||||||
case XK_Left:
|
case XK_Left:
|
||||||
if (tPtr->cursorPosition > 0) {
|
if (tPtr->cursorPosition > 0) {
|
||||||
int i;
|
int i;
|
||||||
paintCursor(tPtr);
|
|
||||||
|
|
||||||
i = tPtr->cursorPosition;
|
i = tPtr->cursorPosition;
|
||||||
i += oneUTF8CharBackward(&tPtr->text[i], i);
|
i += oneUTF8CharBackward(&tPtr->text[i], i);
|
||||||
@@ -1045,9 +1046,8 @@ static void handleTextFieldKeyPress(TextField * tPtr, XEvent * event)
|
|||||||
|
|
||||||
if (tPtr->cursorPosition < tPtr->viewPosition) {
|
if (tPtr->cursorPosition < tPtr->viewPosition) {
|
||||||
tPtr->viewPosition = tPtr->cursorPosition;
|
tPtr->viewPosition = tPtr->cursorPosition;
|
||||||
refresh = 1;
|
}
|
||||||
} else
|
refresh = 1;
|
||||||
paintCursor(tPtr);
|
|
||||||
}
|
}
|
||||||
if (shifted)
|
if (shifted)
|
||||||
cancelSelection = 0;
|
cancelSelection = 0;
|
||||||
@@ -1070,7 +1070,6 @@ static void handleTextFieldKeyPress(TextField * tPtr, XEvent * event)
|
|||||||
case XK_Right:
|
case XK_Right:
|
||||||
if (tPtr->cursorPosition < tPtr->textLen) {
|
if (tPtr->cursorPosition < tPtr->textLen) {
|
||||||
int i;
|
int i;
|
||||||
paintCursor(tPtr);
|
|
||||||
|
|
||||||
i = tPtr->cursorPosition;
|
i = tPtr->cursorPosition;
|
||||||
if (controled) {
|
if (controled) {
|
||||||
@@ -1083,10 +1082,8 @@ static void handleTextFieldKeyPress(TextField * tPtr, XEvent * event)
|
|||||||
}
|
}
|
||||||
tPtr->cursorPosition = i;
|
tPtr->cursorPosition = i;
|
||||||
|
|
||||||
refresh = incrToFit2(tPtr);
|
incrToFit2(tPtr);
|
||||||
|
refresh = 1;
|
||||||
if (!refresh)
|
|
||||||
paintCursor(tPtr);
|
|
||||||
}
|
}
|
||||||
if (shifted)
|
if (shifted)
|
||||||
cancelSelection = 0;
|
cancelSelection = 0;
|
||||||
@@ -1109,13 +1106,11 @@ static void handleTextFieldKeyPress(TextField * tPtr, XEvent * event)
|
|||||||
case XK_Home:
|
case XK_Home:
|
||||||
if (!controled) {
|
if (!controled) {
|
||||||
if (tPtr->cursorPosition > 0) {
|
if (tPtr->cursorPosition > 0) {
|
||||||
paintCursor(tPtr);
|
|
||||||
tPtr->cursorPosition = 0;
|
tPtr->cursorPosition = 0;
|
||||||
if (tPtr->viewPosition > 0) {
|
if (tPtr->viewPosition > 0) {
|
||||||
tPtr->viewPosition = 0;
|
tPtr->viewPosition = 0;
|
||||||
refresh = 1;
|
}
|
||||||
} else
|
refresh = 1;
|
||||||
paintCursor(tPtr);
|
|
||||||
}
|
}
|
||||||
if (shifted)
|
if (shifted)
|
||||||
cancelSelection = 0;
|
cancelSelection = 0;
|
||||||
@@ -1138,14 +1133,11 @@ static void handleTextFieldKeyPress(TextField * tPtr, XEvent * event)
|
|||||||
case XK_End:
|
case XK_End:
|
||||||
if (!controled) {
|
if (!controled) {
|
||||||
if (tPtr->cursorPosition < tPtr->textLen) {
|
if (tPtr->cursorPosition < tPtr->textLen) {
|
||||||
paintCursor(tPtr);
|
|
||||||
tPtr->cursorPosition = tPtr->textLen;
|
tPtr->cursorPosition = tPtr->textLen;
|
||||||
tPtr->viewPosition = 0;
|
tPtr->viewPosition = 0;
|
||||||
|
|
||||||
refresh = incrToFit(tPtr);
|
incrToFit(tPtr);
|
||||||
|
refresh = 1;
|
||||||
if (!refresh)
|
|
||||||
paintCursor(tPtr);
|
|
||||||
}
|
}
|
||||||
if (shifted)
|
if (shifted)
|
||||||
cancelSelection = 0;
|
cancelSelection = 0;
|
||||||
@@ -1408,7 +1400,25 @@ static void handleTextFieldActionEvents(XEvent * event, void *data)
|
|||||||
tPtr->viewPosition);
|
tPtr->viewPosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
tPtr->cursorPosition = pointToCursorPosition(tPtr, event->xmotion.x);
|
if (tPtr->flags.alignment == WARight) {
|
||||||
|
int textWidth = WMWidthOfString(tPtr->font, tPtr->text, tPtr->textLen);
|
||||||
|
if (textWidth < tPtr->usableWidth) {
|
||||||
|
tPtr->cursorPosition = pointToCursorPosition(tPtr,
|
||||||
|
event->xmotion.x - tPtr->usableWidth + textWidth);
|
||||||
|
} else {
|
||||||
|
tPtr->cursorPosition = pointToCursorPosition(tPtr, event->xmotion.x);
|
||||||
|
}
|
||||||
|
} else if (tPtr->flags.alignment == WACenter) {
|
||||||
|
int textWidth = WMWidthOfString(tPtr->font, tPtr->text, tPtr->textLen);
|
||||||
|
if (textWidth < tPtr->usableWidth) {
|
||||||
|
tPtr->cursorPosition = pointToCursorPosition(tPtr,
|
||||||
|
event->xmotion.x - (tPtr->usableWidth - textWidth) / 2);
|
||||||
|
} else {
|
||||||
|
tPtr->cursorPosition = pointToCursorPosition(tPtr, event->xmotion.x);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
tPtr->cursorPosition = pointToCursorPosition(tPtr, event->xmotion.x);
|
||||||
|
}
|
||||||
|
|
||||||
/* Do not allow text selection in secure textfields */
|
/* Do not allow text selection in secure textfields */
|
||||||
if (tPtr->flags.secure) {
|
if (tPtr->flags.secure) {
|
||||||
@@ -1441,17 +1451,35 @@ static void handleTextFieldActionEvents(XEvent * event, void *data)
|
|||||||
if (tPtr->flags.enabled && !tPtr->flags.focused) {
|
if (tPtr->flags.enabled && !tPtr->flags.focused) {
|
||||||
WMSetFocusToWidget(tPtr);
|
WMSetFocusToWidget(tPtr);
|
||||||
}
|
}
|
||||||
|
if (textWidth < tPtr->usableWidth) {
|
||||||
|
tPtr->cursorPosition = pointToCursorPosition(tPtr,
|
||||||
|
event->xbutton.x - tPtr->usableWidth
|
||||||
|
+ textWidth);
|
||||||
|
} else
|
||||||
|
tPtr->cursorPosition = pointToCursorPosition(tPtr, event->xbutton.x);
|
||||||
|
|
||||||
if (tPtr->flags.focused) {
|
if (tPtr->flags.focused) {
|
||||||
tPtr->selection.position = tPtr->cursorPosition;
|
tPtr->selection.position = tPtr->cursorPosition;
|
||||||
tPtr->selection.count = 0;
|
tPtr->selection.count = 0;
|
||||||
}
|
}
|
||||||
|
paintTextField(tPtr);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WACenter:
|
||||||
|
textWidth = WMWidthOfString(tPtr->font, tPtr->text, tPtr->textLen);
|
||||||
|
if (tPtr->flags.enabled && !tPtr->flags.focused) {
|
||||||
|
WMSetFocusToWidget(tPtr);
|
||||||
|
}
|
||||||
if (textWidth < tPtr->usableWidth) {
|
if (textWidth < tPtr->usableWidth) {
|
||||||
tPtr->cursorPosition = pointToCursorPosition(tPtr,
|
tPtr->cursorPosition = pointToCursorPosition(tPtr,
|
||||||
event->xbutton.x - tPtr->usableWidth
|
event->xbutton.x - (tPtr->usableWidth - textWidth) / 2);
|
||||||
+ textWidth);
|
} else {
|
||||||
} else
|
|
||||||
tPtr->cursorPosition = pointToCursorPosition(tPtr, event->xbutton.x);
|
tPtr->cursorPosition = pointToCursorPosition(tPtr, event->xbutton.x);
|
||||||
|
}
|
||||||
|
if (tPtr->flags.focused) {
|
||||||
|
tPtr->selection.position = tPtr->cursorPosition;
|
||||||
|
tPtr->selection.count = 0;
|
||||||
|
}
|
||||||
paintTextField(tPtr);
|
paintTextField(tPtr);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -1465,29 +1493,31 @@ static void handleTextFieldActionEvents(XEvent * event, void *data)
|
|||||||
tPtr->selection.count = 0;
|
tPtr->selection.count = 0;
|
||||||
paintTextField(tPtr);
|
paintTextField(tPtr);
|
||||||
}
|
}
|
||||||
if (event->xbutton.button == Button2 && tPtr->flags.enabled) {
|
|
||||||
char *text;
|
|
||||||
int n;
|
|
||||||
|
|
||||||
if (!WMRequestSelection(tPtr->view, XA_PRIMARY, XA_STRING,
|
|
||||||
event->xbutton.time, pasteText, NULL)) {
|
|
||||||
text = XFetchBuffer(tPtr->view->screen->display, &n, 0);
|
|
||||||
|
|
||||||
if (text) {
|
|
||||||
text[n] = 0;
|
|
||||||
WMInsertTextFieldText(tPtr, text, tPtr->cursorPosition);
|
|
||||||
XFree(text);
|
|
||||||
NOTIFY(tPtr, didChange, WMTextDidChangeNotification,
|
|
||||||
(void *)WMInsertTextEvent);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
tPtr->flags.waitingSelection = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (event->xbutton.button == Button2 && tPtr->flags.enabled) {
|
||||||
|
char *text;
|
||||||
|
int n;
|
||||||
|
|
||||||
|
if (!WMRequestSelection(tPtr->view, XA_PRIMARY, XA_STRING,
|
||||||
|
event->xbutton.time, pasteText, NULL)) {
|
||||||
|
text = XFetchBuffer(tPtr->view->screen->display, &n, 0);
|
||||||
|
|
||||||
|
if (text) {
|
||||||
|
text[n] = 0;
|
||||||
|
WMInsertTextFieldText(tPtr, text, tPtr->cursorPosition);
|
||||||
|
XFree(text);
|
||||||
|
NOTIFY(tPtr, didChange, WMTextDidChangeNotification,
|
||||||
|
(void *)WMInsertTextEvent);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
tPtr->flags.waitingSelection = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ButtonRelease:
|
case ButtonRelease:
|
||||||
|
|||||||
+134
-2
@@ -4,7 +4,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 2014-2023 Window Maker Team
|
* Copyright (c) 2014-2023 Window Maker Team
|
||||||
* Copyright (c) 1998-2003 Alfredo K. Kojima
|
* Copyright (c) 1998-2003 Alfredo K. Kojima
|
||||||
* Copyright (c) 2009-2023 Window Maker Team
|
* Copyright (c) 2009-2026 Window Maker Team
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -72,9 +72,15 @@ static struct expert_option {
|
|||||||
{ N_("Cycle windows only on the active head."),
|
{ N_("Cycle windows only on the active head."),
|
||||||
/* default: */ False, OPTION_WMAKER, "CycleActiveHeadOnly" },
|
/* default: */ False, OPTION_WMAKER, "CycleActiveHeadOnly" },
|
||||||
|
|
||||||
|
{ N_("Cycle all windows from all workspaces."),
|
||||||
|
/* default: */ False, OPTION_WMAKER, "CycleAllWorkspaces" },
|
||||||
|
|
||||||
{ N_("Ignore minimized windows when cycling."),
|
{ N_("Ignore minimized windows when cycling."),
|
||||||
/* default: */ False, OPTION_WMAKER, "CycleIgnoreMinimized" },
|
/* default: */ False, OPTION_WMAKER, "CycleIgnoreMinimized" },
|
||||||
|
|
||||||
|
{ N_("Show app icons in window list."),
|
||||||
|
/* default: */ False, OPTION_WMAKER, "WindowListAppIcons" },
|
||||||
|
|
||||||
{ N_("Show switch panel when cycling windows."),
|
{ N_("Show switch panel when cycling windows."),
|
||||||
/* default: */ True, OPTION_WMAKER_ARRAY, "SwitchPanelImages" },
|
/* default: */ True, OPTION_WMAKER_ARRAY, "SwitchPanelImages" },
|
||||||
|
|
||||||
@@ -141,6 +147,8 @@ typedef struct _Panel {
|
|||||||
WMButton *swi[wlengthof_nocheck(expert_options)];
|
WMButton *swi[wlengthof_nocheck(expert_options)];
|
||||||
|
|
||||||
WMTextField *textfield[wlengthof_nocheck(expert_options)];
|
WMTextField *textfield[wlengthof_nocheck(expert_options)];
|
||||||
|
WMScrollView *sv;
|
||||||
|
WMWidget *frame;
|
||||||
|
|
||||||
} _Panel;
|
} _Panel;
|
||||||
|
|
||||||
@@ -161,6 +169,124 @@ static void changeIntTextfield(void *data, int delta)
|
|||||||
WMSetTextFieldText(textfield, buffer);
|
WMSetTextFieldText(textfield, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void scrollViewWheelHandler(XEvent *event, void *data)
|
||||||
|
{
|
||||||
|
_Panel *panel = (_Panel *) data;
|
||||||
|
int amount, viewH, contentH, newY, maxY;
|
||||||
|
WMRect rect;
|
||||||
|
WMPoint pt;
|
||||||
|
|
||||||
|
if (!panel || !panel->sv || !panel->frame)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (event->type != ButtonPress)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (event->xbutton.button != WINGsConfiguration.mouseWheelUp &&
|
||||||
|
event->xbutton.button != WINGsConfiguration.mouseWheelDown)
|
||||||
|
return;
|
||||||
|
|
||||||
|
rect = WMGetScrollViewVisibleRect(panel->sv);
|
||||||
|
viewH = rect.size.height;
|
||||||
|
contentH = WMWidgetHeight(panel->frame);
|
||||||
|
|
||||||
|
if (event->xbutton.state & ControlMask) {
|
||||||
|
amount = viewH; /* page */
|
||||||
|
} else if (event->xbutton.state & ShiftMask) {
|
||||||
|
amount = 1; /* line */
|
||||||
|
} else {
|
||||||
|
amount = viewH / 3; /* default */
|
||||||
|
if (amount == 0)
|
||||||
|
amount = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event->xbutton.button == WINGsConfiguration.mouseWheelUp)
|
||||||
|
amount = -amount;
|
||||||
|
|
||||||
|
newY = rect.pos.y + amount;
|
||||||
|
maxY = contentH - viewH;
|
||||||
|
if (maxY < 0)
|
||||||
|
maxY = 0;
|
||||||
|
if (newY < 0)
|
||||||
|
newY = 0;
|
||||||
|
if (newY > maxY)
|
||||||
|
newY = maxY;
|
||||||
|
|
||||||
|
pt.x = rect.pos.x;
|
||||||
|
pt.y = newY;
|
||||||
|
|
||||||
|
WMScrollViewScrollPoint(panel->sv, pt);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void scrollViewRealizeObserver(void *self, WMNotification *not)
|
||||||
|
{
|
||||||
|
(void) not;
|
||||||
|
_Panel *panel = (_Panel *) self;
|
||||||
|
Display *dpy = NULL;
|
||||||
|
Window viewport_win = 0;
|
||||||
|
WMView *frameView;
|
||||||
|
|
||||||
|
if (!panel || !panel->frame)
|
||||||
|
return;
|
||||||
|
|
||||||
|
frameView = WMWidgetView(panel->frame);
|
||||||
|
|
||||||
|
if (frameView && frameView->parent) {
|
||||||
|
dpy = frameView->screen->display;
|
||||||
|
viewport_win = frameView->parent->window;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fallback: use the scrollview's view window if parent viewport not available */
|
||||||
|
if (!viewport_win && panel->sv) {
|
||||||
|
WMView *svView = WMWidgetView(panel->sv);
|
||||||
|
if (svView && svView->screen) {
|
||||||
|
dpy = svView->screen->display;
|
||||||
|
viewport_win = svView->window;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!dpy || viewport_win == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
XGrabButton(dpy, WINGsConfiguration.mouseWheelUp, AnyModifier, viewport_win,
|
||||||
|
True, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None);
|
||||||
|
XGrabButton(dpy, WINGsConfiguration.mouseWheelDown, AnyModifier, viewport_win,
|
||||||
|
True, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void scrollViewPrepareForClose(Panel *p)
|
||||||
|
{
|
||||||
|
_Panel *panel = (_Panel *) p;
|
||||||
|
Display *dpy = NULL;
|
||||||
|
Window viewport_win = 0;
|
||||||
|
|
||||||
|
if (!panel)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (panel->frame) {
|
||||||
|
WMView *frameView = WMWidgetView(panel->frame);
|
||||||
|
if (frameView && frameView->parent) {
|
||||||
|
dpy = frameView->screen->display;
|
||||||
|
viewport_win = frameView->parent->window;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!viewport_win && panel->sv) {
|
||||||
|
WMView *svView = WMWidgetView(panel->sv);
|
||||||
|
if (svView && svView->screen) {
|
||||||
|
dpy = svView->screen->display;
|
||||||
|
viewport_win = svView->window;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dpy && viewport_win != 0) {
|
||||||
|
XUngrabButton(dpy, WINGsConfiguration.mouseWheelUp, AnyModifier, viewport_win);
|
||||||
|
XUngrabButton(dpy, WINGsConfiguration.mouseWheelDown, AnyModifier, viewport_win);
|
||||||
|
}
|
||||||
|
|
||||||
|
WMRemoveNotificationObserver(panel);
|
||||||
|
}
|
||||||
|
|
||||||
static void downButtonCallback(WMWidget *self, void *data)
|
static void downButtonCallback(WMWidget *self, void *data)
|
||||||
{
|
{
|
||||||
(void) self;
|
(void) self;
|
||||||
@@ -284,7 +410,7 @@ static void createPanel(Panel *p)
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
wwarning("export_options[%d].class = %d, this should not happen\n",
|
wwarning("expert_options[%d].class = %d, this should not happen\n",
|
||||||
i, expert_options[i].class);
|
i, expert_options[i].class);
|
||||||
#endif
|
#endif
|
||||||
state = expert_options[i].def_state;
|
state = expert_options[i].def_state;
|
||||||
@@ -296,6 +422,11 @@ static void createPanel(Panel *p)
|
|||||||
|
|
||||||
WMMapSubwidgets(panel->box);
|
WMMapSubwidgets(panel->box);
|
||||||
WMSetScrollViewContentView(sv, WMWidgetView(f));
|
WMSetScrollViewContentView(sv, WMWidgetView(f));
|
||||||
|
/* keep references for the wheel handler and register it */
|
||||||
|
panel->sv = sv;
|
||||||
|
panel->frame = f;
|
||||||
|
WMCreateEventHandler(WMWidgetView(sv), ButtonPressMask, scrollViewWheelHandler, panel);
|
||||||
|
WMAddNotificationObserver(scrollViewRealizeObserver, panel, WMViewRealizedNotification, WMWidgetView(sv));
|
||||||
WMRealizeWidget(panel->box);
|
WMRealizeWidget(panel->box);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -356,6 +487,7 @@ Panel *InitExpert(WMWidget *parent)
|
|||||||
|
|
||||||
panel->callbacks.createWidgets = createPanel;
|
panel->callbacks.createWidgets = createPanel;
|
||||||
panel->callbacks.updateDomain = storeDefaults;
|
panel->callbacks.updateDomain = storeDefaults;
|
||||||
|
panel->callbacks.prepareForClose = scrollViewPrepareForClose;
|
||||||
|
|
||||||
AddSection(panel, ICON_FILE);
|
AddSection(panel, ICON_FILE);
|
||||||
|
|
||||||
|
|||||||
@@ -257,7 +257,7 @@ static void createPanel(Panel * p)
|
|||||||
WMMoveWidget(panel->hcdescF, 15, 130);
|
WMMoveWidget(panel->hcdescF, 15, 130);
|
||||||
|
|
||||||
panel->hcdescL = WMCreateLabel(panel->hcdescF);
|
panel->hcdescL = WMCreateLabel(panel->hcdescF);
|
||||||
WMResizeWidget(panel->hcdescL, 200, 60);
|
WMResizeWidget(panel->hcdescL, 200, 70);
|
||||||
WMMoveWidget(panel->hcdescL, 15, 10);
|
WMMoveWidget(panel->hcdescL, 15, 10);
|
||||||
WMSetLabelText(panel->hcdescL,
|
WMSetLabelText(panel->hcdescL,
|
||||||
_("Instructions:\n\n"
|
_("Instructions:\n\n"
|
||||||
|
|||||||
@@ -284,14 +284,14 @@ static void createPanel(Panel * p)
|
|||||||
|
|
||||||
/***************** Options ****************/
|
/***************** Options ****************/
|
||||||
panel->optF = WMCreateFrame(panel->box);
|
panel->optF = WMCreateFrame(panel->box);
|
||||||
WMResizeWidget(panel->optF, 255, 94);
|
WMResizeWidget(panel->optF, 255, 96);
|
||||||
WMMoveWidget(panel->optF, 15, 125);
|
WMMoveWidget(panel->optF, 15, 125);
|
||||||
WMSetFrameTitle(panel->optF, _("AppIcon bouncing"));
|
WMSetFrameTitle(panel->optF, _("AppIcon bouncing"));
|
||||||
|
|
||||||
for (i = 0; i < wlengthof(appicon_bouncing); i++) {
|
for (i = 0; i < wlengthof(appicon_bouncing); i++) {
|
||||||
panel->bounceB[i] = WMCreateSwitchButton(panel->optF);
|
panel->bounceB[i] = WMCreateSwitchButton(panel->optF);
|
||||||
WMResizeWidget(panel->bounceB[i], 237, 26);
|
WMResizeWidget(panel->bounceB[i], 237, 26);
|
||||||
WMMoveWidget(panel->bounceB[i], 9, 14 + i * 25);
|
WMMoveWidget(panel->bounceB[i], 9, 16 + i * 26);
|
||||||
WMSetButtonText(panel->bounceB[i], _(appicon_bouncing[i].label));
|
WMSetButtonText(panel->bounceB[i], _(appicon_bouncing[i].label));
|
||||||
|
|
||||||
if (appicon_bouncing[i].default_value)
|
if (appicon_bouncing[i].default_value)
|
||||||
@@ -306,7 +306,7 @@ static void createPanel(Panel * p)
|
|||||||
|
|
||||||
/***************** Workspace border ****************/
|
/***************** Workspace border ****************/
|
||||||
panel->borderF = WMCreateFrame(panel->box);
|
panel->borderF = WMCreateFrame(panel->box);
|
||||||
WMResizeWidget(panel->borderF, 220, 75);
|
WMResizeWidget(panel->borderF, 220, 77);
|
||||||
WMMoveWidget(panel->borderF, 285, 144);
|
WMMoveWidget(panel->borderF, 285, 144);
|
||||||
WMSetFrameTitle(panel->borderF, _("Workspace border"));
|
WMSetFrameTitle(panel->borderF, _("Workspace border"));
|
||||||
|
|
||||||
|
|||||||
@@ -26,4 +26,4 @@ et.po Estonian Ivar Smolin <okul@linux.ee>
|
|||||||
ca.po Catalan Ernest Adrogué <eadrogue@gmx.net>
|
ca.po Catalan Ernest Adrogué <eadrogue@gmx.net>
|
||||||
nl.po Dutch Alwin <translations@ziggo.nl>
|
nl.po Dutch Alwin <translations@ziggo.nl>
|
||||||
fy.po Frisian Alwin <translations@ziggo.nl>
|
fy.po Frisian Alwin <translations@ziggo.nl>
|
||||||
sr.po Serbian Strahinya Radich <contact@strahinja.org>
|
sr.po Serbian Strahinya Radich <sr@strahinja.org>
|
||||||
|
|||||||
+2
-2
@@ -3,7 +3,7 @@
|
|||||||
# 1998-2006 Dan Pascu
|
# 1998-2006 Dan Pascu
|
||||||
# 2013-2020 Window Maker Developers Team
|
# 2013-2020 Window Maker Developers Team
|
||||||
# This file is distributed under the same license as the Window Maker package.
|
# This file is distributed under the same license as the Window Maker package.
|
||||||
# Strahinya Radich (Страхиња Радић) <contact@strahinja.org>, 2023.
|
# Strahinya Radich (Страхиња Радић) <sr@strahinja.org>, 2023.
|
||||||
#
|
#
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -11,7 +11,7 @@ msgstr ""
|
|||||||
"Report-Msgid-Bugs-To: wmaker-dev@googlegroups.com\n"
|
"Report-Msgid-Bugs-To: wmaker-dev@googlegroups.com\n"
|
||||||
"POT-Creation-Date: 2023-11-02 19:25+0100\n"
|
"POT-Creation-Date: 2023-11-02 19:25+0100\n"
|
||||||
"PO-Revision-Date: 2023-11-02 19:48+0100\n"
|
"PO-Revision-Date: 2023-11-02 19:48+0100\n"
|
||||||
"Last-Translator: Страхиња Радић <contact@strahinja.org>\n"
|
"Last-Translator: Страхиња Радић <sr@strahinja.org>\n"
|
||||||
"Language-Team: Serbian <sr@li.org>\n"
|
"Language-Team: Serbian <sr@li.org>\n"
|
||||||
"Language: sr\n"
|
"Language: sr\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
|
|||||||
@@ -233,7 +233,7 @@
|
|||||||
ScreenSwitchKey = None;
|
ScreenSwitchKey = None;
|
||||||
RunKey = None;
|
RunKey = None;
|
||||||
ExitKey = None;
|
ExitKey = None;
|
||||||
ScreenCaptureKey = Print;
|
ScreenCaptureKey = None;
|
||||||
WindowCaptureKey = None;
|
WindowCaptureKey = None;
|
||||||
PartialCaptureKey = None;
|
PartialCaptureKey = None;
|
||||||
NormalCursor = (builtin, left_ptr);
|
NormalCursor = (builtin, left_ptr);
|
||||||
@@ -252,5 +252,7 @@
|
|||||||
SelectCursor = (builtin, cross);
|
SelectCursor = (builtin, cross);
|
||||||
DialogHistoryLines = 500;
|
DialogHistoryLines = 500;
|
||||||
CycleActiveHeadOnly = NO;
|
CycleActiveHeadOnly = NO;
|
||||||
|
CycleAllWorkspaces = NO;
|
||||||
CycleIgnoreMinimized = NO;
|
CycleIgnoreMinimized = NO;
|
||||||
|
WindowListAppIcons = NO;
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -64,7 +64,7 @@ menu.bg Bulgarian Slavei Karadjov <slaff@exco.net>
|
|||||||
menu.sk Slovak judas@hell <tomka@oalevice.sk>
|
menu.sk Slovak judas@hell <tomka@oalevice.sk>
|
||||||
menu.nl Dutch Alwin <translations@ziggo.nl>
|
menu.nl Dutch Alwin <translations@ziggo.nl>
|
||||||
menu.fy Frisian Alwin <translations@ziggo.nl>
|
menu.fy Frisian Alwin <translations@ziggo.nl>
|
||||||
menu.sr Serbian Strahinya Radich <contact@strahinja.org>
|
menu.sr Serbian Strahinya Radich <sr@strahinja.org>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -81,5 +81,5 @@ plmenu.sk Slovak judas@hell <tomka@oalevice.sk>
|
|||||||
plmenu.ja Japanese Seiichi SATO <sato@cvs-net.co.jp>
|
plmenu.ja Japanese Seiichi SATO <sato@cvs-net.co.jp>
|
||||||
plmenu.nl Dutch Alwin <translations@ziggo.nl>
|
plmenu.nl Dutch Alwin <translations@ziggo.nl>
|
||||||
plmenu.fy Frisian Alwin <translations@ziggo.nl>
|
plmenu.fy Frisian Alwin <translations@ziggo.nl>
|
||||||
plmenu.sr Serbian Strahinya Radich <contact@strahinja.org>
|
plmenu.sr Serbian Strahinya Radich <sr@strahinja.org>
|
||||||
|
|
||||||
|
|||||||
@@ -4,4 +4,3 @@ Comment=This session logs you into Window Maker
|
|||||||
Exec=wmaker
|
Exec=wmaker
|
||||||
TryExec=wmaker
|
TryExec=wmaker
|
||||||
DesktopNames=WindowMaker
|
DesktopNames=WindowMaker
|
||||||
X-GDM-SessionRegisters=true
|
|
||||||
|
|||||||
+50
-4
@@ -71,16 +71,16 @@ dnl 6. If any interfaces have been removed or changed since the last
|
|||||||
dnl public release, then set age to 0.
|
dnl public release, then set age to 0.
|
||||||
dnl
|
dnl
|
||||||
dnl libwraster
|
dnl libwraster
|
||||||
WRASTER_CURRENT=7
|
WRASTER_CURRENT=8
|
||||||
WRASTER_REVISION=0
|
WRASTER_REVISION=0
|
||||||
WRASTER_AGE=1
|
WRASTER_AGE=2
|
||||||
WRASTER_VERSION=$WRASTER_CURRENT:$WRASTER_REVISION:$WRASTER_AGE
|
WRASTER_VERSION=$WRASTER_CURRENT:$WRASTER_REVISION:$WRASTER_AGE
|
||||||
AC_SUBST(WRASTER_VERSION)
|
AC_SUBST(WRASTER_VERSION)
|
||||||
dnl
|
dnl
|
||||||
dnl libWINGs
|
dnl libWINGs
|
||||||
WINGS_CURRENT=5
|
WINGS_CURRENT=6
|
||||||
WINGS_REVISION=0
|
WINGS_REVISION=0
|
||||||
WINGS_AGE=2
|
WINGS_AGE=3
|
||||||
WINGS_VERSION=$WINGS_CURRENT:$WINGS_REVISION:$WINGS_AGE
|
WINGS_VERSION=$WINGS_CURRENT:$WINGS_REVISION:$WINGS_AGE
|
||||||
AC_SUBST(WINGS_VERSION)
|
AC_SUBST(WINGS_VERSION)
|
||||||
dnl
|
dnl
|
||||||
@@ -130,6 +130,20 @@ AS_IF([test "x$debug" = "xyes"],
|
|||||||
])
|
])
|
||||||
|
|
||||||
|
|
||||||
|
dnl Native CPU Optimizations Option
|
||||||
|
dnl =================
|
||||||
|
m4_divert_push([INIT_PREPARE])dnl
|
||||||
|
AC_ARG_ENABLE([native],
|
||||||
|
[AS_HELP_STRING([--enable-native], [enable native option, @<:@default=no@:>@])],
|
||||||
|
[AS_CASE(["$enableval"],
|
||||||
|
[yes], [native=yes],
|
||||||
|
[no], [native=no],
|
||||||
|
[AC_MSG_ERROR([bad value $enableval for --enable-native])] )],
|
||||||
|
[native=no])
|
||||||
|
m4_divert_pop([INIT_PREPARE])dnl
|
||||||
|
AS_IF([test "x$native" = "xyes"],
|
||||||
|
[AX_CFLAGS_GCC_OPTION([-march=native])])
|
||||||
|
|
||||||
AX_CFLAGS_GCC_OPTION([-Wall])
|
AX_CFLAGS_GCC_OPTION([-Wall])
|
||||||
AX_CFLAGS_GCC_OPTION([-Wextra -Wno-sign-compare])
|
AX_CFLAGS_GCC_OPTION([-Wextra -Wno-sign-compare])
|
||||||
dnl
|
dnl
|
||||||
@@ -766,6 +780,19 @@ m4_divert_pop([INIT_PREPARE])dnl
|
|||||||
WM_IMGFMT_CHECK_JPEG
|
WM_IMGFMT_CHECK_JPEG
|
||||||
|
|
||||||
|
|
||||||
|
dnl JXL Support
|
||||||
|
dnl ============
|
||||||
|
m4_divert_push([INIT_PREPARE])dnl
|
||||||
|
AC_ARG_ENABLE([jxl],
|
||||||
|
[AS_HELP_STRING([--disable-jxl], [disable JXL support through libjxl])],
|
||||||
|
[AS_CASE(["$enableval"],
|
||||||
|
[yes|no], [],
|
||||||
|
[AC_MSG_ERROR([bad value $enableval for --enable-jxl])] )],
|
||||||
|
[enable_jxl=auto])
|
||||||
|
m4_divert_pop([INIT_PREPARE])dnl
|
||||||
|
WM_IMGFMT_CHECK_JXL
|
||||||
|
|
||||||
|
|
||||||
dnl GIF Support
|
dnl GIF Support
|
||||||
dnl ============
|
dnl ============
|
||||||
m4_divert_push([INIT_PREPARE])dnl
|
m4_divert_push([INIT_PREPARE])dnl
|
||||||
@@ -844,6 +871,22 @@ AM_CONDITIONAL([ICON_EXT_XPM], [test "x$ICONEXT" = "xxpm"])
|
|||||||
AM_CONDITIONAL([ICON_EXT_TIFF], [test "x$ICONEXT" = "xtiff"])
|
AM_CONDITIONAL([ICON_EXT_TIFF], [test "x$ICONEXT" = "xtiff"])
|
||||||
|
|
||||||
|
|
||||||
|
dnl Archive Support for wmiv
|
||||||
|
dnl =================================
|
||||||
|
dnl Check for libarchive (comprehensive archive support)
|
||||||
|
AC_CHECK_LIB([archive], [archive_read_new], [
|
||||||
|
AC_CHECK_HEADER([archive.h], [
|
||||||
|
AC_DEFINE([HAVE_LIBARCHIVE], [1], [Define if libarchive is available])
|
||||||
|
LIBARCHIVE_LIBS="-larchive"
|
||||||
|
], [
|
||||||
|
AC_MSG_WARN([libarchive header not found, archive support disabled])
|
||||||
|
])
|
||||||
|
], [
|
||||||
|
AC_MSG_WARN([libarchive not found, archive support disabled])
|
||||||
|
])
|
||||||
|
AC_SUBST([LIBARCHIVE_LIBS])
|
||||||
|
|
||||||
|
|
||||||
dnl ==============================================
|
dnl ==============================================
|
||||||
dnl End of Graphic Format Libraries
|
dnl End of Graphic Format Libraries
|
||||||
dnl ==============================================
|
dnl ==============================================
|
||||||
@@ -1008,6 +1051,9 @@ echo "Supported graphic format libraries :$supported_gfx"
|
|||||||
echo "Unsupported features :$unsupported"
|
echo "Unsupported features :$unsupported"
|
||||||
echo "Pango text layout support in WINGs : $pango"
|
echo "Pango text layout support in WINGs : $pango"
|
||||||
echo "Translated languages to support :$supported_locales"
|
echo "Translated languages to support :$supported_locales"
|
||||||
|
AS_IF([test "x$native" = "xyes"],
|
||||||
|
[AS_ECHO(["Target architecture : native"]) ],
|
||||||
|
[AS_ECHO(["Target architecture : generic"]) ])
|
||||||
AS_IF([test "x$WEB_REPO_ROOT" != "x"],
|
AS_IF([test "x$WEB_REPO_ROOT" != "x"],
|
||||||
[AS_ECHO(["Git repository for WMaker's Website : $WEB_REPO_ROOT"]) ])
|
[AS_ECHO(["Git repository for WMaker's Website : $WEB_REPO_ROOT"]) ])
|
||||||
AS_IF([test "x$debug" = "xyes"],
|
AS_IF([test "x$debug" = "xyes"],
|
||||||
|
|||||||
Vendored
+12
@@ -204,6 +204,11 @@ Note that if you don't have it, @command{configure} will issue a big warning in
|
|||||||
this is because JPEG images are often used in themes and for background images
|
this is because JPEG images are often used in themes and for background images
|
||||||
so you probably want this format supported.
|
so you probably want this format supported.
|
||||||
|
|
||||||
|
@item @emph{libjxl} 0.7.0 or newer
|
||||||
|
|
||||||
|
For @emph{JXL} image support,
|
||||||
|
@uref{https://github.com/libjxl/libjxl}
|
||||||
|
|
||||||
@item @emph{libgif} 2.2 or @emph{libungif}
|
@item @emph{libgif} 2.2 or @emph{libungif}
|
||||||
|
|
||||||
For @emph{GIF} image support,
|
For @emph{GIF} image support,
|
||||||
@@ -477,6 +482,9 @@ Disable GIF support in @emph{WRaster} library; when enabled use @file{libgif} or
|
|||||||
@item --disable-jpeg
|
@item --disable-jpeg
|
||||||
Disable JPEG support in @emph{WRaster} library; when enabled use @file{libjpeg}.
|
Disable JPEG support in @emph{WRaster} library; when enabled use @file{libjpeg}.
|
||||||
|
|
||||||
|
@item --disable-jxl
|
||||||
|
Disable JPEG-XL support in @emph{WRaster} library; when enabled use @file{libjxl}.
|
||||||
|
|
||||||
@item --without-libbsd
|
@item --without-libbsd
|
||||||
Refuse use of the @file{libbsd} compatibility library in @emph{WINGs} utility library,
|
Refuse use of the @file{libbsd} compatibility library in @emph{WINGs} utility library,
|
||||||
even if your system provides it.
|
even if your system provides it.
|
||||||
@@ -643,6 +651,10 @@ appropriate requirements and works with this.
|
|||||||
Despite all this, if you think there's a use for it and feel in the mood to help, do not hesitate to
|
Despite all this, if you think there's a use for it and feel in the mood to help, do not hesitate to
|
||||||
discuss on the mailing list @value{emailsupport} to get it working.
|
discuss on the mailing list @value{emailsupport} to get it working.
|
||||||
|
|
||||||
|
@item --enable-native
|
||||||
|
Enable native CPU optimizations by adding @option{-march=native} to the compiler flags, tuning the
|
||||||
|
generated code for the build machine at the expense of portability.
|
||||||
|
|
||||||
@item --with-web-repo=@i{PATH}
|
@item --with-web-repo=@i{PATH}
|
||||||
Enable generation of HTML documentation to be uploaded to @sc{Window Maker}'s website.
|
Enable generation of HTML documentation to be uploaded to @sc{Window Maker}'s website.
|
||||||
The @file{@i{PATH}} is the directory where you have cloned the homepage's repository.
|
The @file{@i{PATH}} is the directory where you have cloned the homepage's repository.
|
||||||
|
|||||||
+8
-8
@@ -12,7 +12,7 @@ necessary.
|
|||||||
.SH "OPTIONS"
|
.SH "OPTIONS"
|
||||||
.TP
|
.TP
|
||||||
.BI \-display " host:display.screen"
|
.BI \-display " host:display.screen"
|
||||||
specify display to use.
|
specify the display to use.
|
||||||
On multiheaded machines, Window Maker will automatically manage all screens.
|
On multiheaded machines, Window Maker will automatically manage all screens.
|
||||||
If you want Window Maker to manage only a specific screen, you must supply
|
If you want Window Maker to manage only a specific screen, you must supply
|
||||||
the screen number you want to have managed with the
|
the screen number you want to have managed with the
|
||||||
@@ -24,13 +24,13 @@ wmaker -display :0.1
|
|||||||
.EE
|
.EE
|
||||||
.TP
|
.TP
|
||||||
.B \-\-dont\-restore
|
.B \-\-dont\-restore
|
||||||
do not restore saved session
|
do not restore the saved session
|
||||||
.TP
|
.TP
|
||||||
.B \-\-global_defaults_path
|
.B \-\-global_defaults_path
|
||||||
print the path where the files for the default configuration are installed and exit
|
print the path where the files for the default configuration are installed and exit
|
||||||
.TP
|
.TP
|
||||||
.B \-\-help
|
.B \-\-help
|
||||||
print the list of command line options supported, one per line, and exit
|
print the list of supported command line options, one per line, and exit
|
||||||
.TP
|
.TP
|
||||||
.BI \-\-locale " locale"
|
.BI \-\-locale " locale"
|
||||||
specify the locale (i18n language) to use; Window Maker will also set the variable
|
specify the locale (i18n language) to use; Window Maker will also set the variable
|
||||||
@@ -38,7 +38,7 @@ specify the locale (i18n language) to use; Window Maker will also set the variab
|
|||||||
which will be inherited by all applications started from Window Maker
|
which will be inherited by all applications started from Window Maker
|
||||||
.TP
|
.TP
|
||||||
.B \-\-no\-autolaunch
|
.B \-\-no\-autolaunch
|
||||||
do not launch at start-up the applications that were marked in the configuration as autolanched
|
do not launch at start-up the applications that were marked in the configuration as autolaunched
|
||||||
.TP
|
.TP
|
||||||
.B \-\-no\-clip
|
.B \-\-no\-clip
|
||||||
do not show the workspace Clip
|
do not show the workspace Clip
|
||||||
@@ -53,7 +53,7 @@ disable the Drawers in the Dock
|
|||||||
@!HAVE_INOTIFY@disable the periodic check on the configuration file to reload it automatically
|
@!HAVE_INOTIFY@disable the periodic check on the configuration file to reload it automatically
|
||||||
@USE_ICCCM_WMREPLACE@.TP
|
@USE_ICCCM_WMREPLACE@.TP
|
||||||
@USE_ICCCM_WMREPLACE@.B \-\-replace
|
@USE_ICCCM_WMREPLACE@.B \-\-replace
|
||||||
@USE_ICCCM_WMREPLACE@ask the currently running window manager to let Window Maker take his place
|
@USE_ICCCM_WMREPLACE@ask the currently running window manager to let Window Maker take its place
|
||||||
.TP
|
.TP
|
||||||
.B \-\-static
|
.B \-\-static
|
||||||
do not update or save automatically the configuration
|
do not update or save automatically the configuration
|
||||||
@@ -88,7 +88,7 @@ few options not available using the Attributes Editor.
|
|||||||
.B @pkgconfdir@/
|
.B @pkgconfdir@/
|
||||||
All the above-mentioned files are READ from here if not found except
|
All the above-mentioned files are READ from here if not found except
|
||||||
for WMState, which is COPIED from here. No matter where they are read
|
for WMState, which is COPIED from here. No matter where they are read
|
||||||
from, if it's necessary to write configuration changes back into this
|
from, if it's necessary to write configuration changes back into these
|
||||||
files, user's files will be written to.
|
files, user's files will be written to.
|
||||||
.TP
|
.TP
|
||||||
.B ~/GNUstep/Library/WindowMaker/autostart
|
.B ~/GNUstep/Library/WindowMaker/autostart
|
||||||
@@ -108,7 +108,7 @@ might be shut down before the script is executed.
|
|||||||
The menu file indicated in WMRootMenu is looked for here...
|
The menu file indicated in WMRootMenu is looked for here...
|
||||||
.TP
|
.TP
|
||||||
.B @pkgdatadir@/
|
.B @pkgdatadir@/
|
||||||
and here, in that order. Unless, the indicated path is an absolute path.
|
and here, in that order. Unless the indicated path is an absolute path.
|
||||||
.TP
|
.TP
|
||||||
.B ~/GNUstep/Library/WindowMaker/Pixmaps/
|
.B ~/GNUstep/Library/WindowMaker/Pixmaps/
|
||||||
Window Maker looks for \fBpixmaps\fP here
|
Window Maker looks for \fBpixmaps\fP here
|
||||||
@@ -131,7 +131,7 @@ Window Maker looks for theme files here (ibid)
|
|||||||
System-wide (Window Maker-specific) pixmaps are located here
|
System-wide (Window Maker-specific) pixmaps are located here
|
||||||
.TP
|
.TP
|
||||||
.B @pkgdatadir@/Styles/
|
.B @pkgdatadir@/Styles/
|
||||||
System wide styles are here
|
System-wide styles are here
|
||||||
.TP
|
.TP
|
||||||
.B @pkgdatadir@/Themes/
|
.B @pkgdatadir@/Themes/
|
||||||
Guess... ;-)
|
Guess... ;-)
|
||||||
|
|||||||
+26
-17
@@ -3,11 +3,14 @@
|
|||||||
wmiv \- quick image viewer using wrlib
|
wmiv \- quick image viewer using wrlib
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
.B wmiv
|
.B wmiv
|
||||||
.RI [ \,image(s)\/ | \,directory\/ ]
|
.RI [ \,image(s)\/ | \,directory\/ | \,archive\/]
|
||||||
.SH OPTIONS
|
.SH OPTIONS
|
||||||
.TP
|
.TP
|
||||||
.B \-\-help
|
.B \-\-help
|
||||||
print help text
|
display this help
|
||||||
|
.TP
|
||||||
|
.B \-\-ignore-unknown
|
||||||
|
ignore unknown image format
|
||||||
.TP
|
.TP
|
||||||
.B \-\-version
|
.B \-\-version
|
||||||
print version
|
print version
|
||||||
@@ -19,21 +22,6 @@ zoom in
|
|||||||
[\-]
|
[\-]
|
||||||
zoom out
|
zoom out
|
||||||
.TP
|
.TP
|
||||||
[Esc]
|
|
||||||
actual size
|
|
||||||
.TP
|
|
||||||
[D]
|
|
||||||
launch diaporama mode
|
|
||||||
.TP
|
|
||||||
[L]
|
|
||||||
rotate image on the left
|
|
||||||
.TP
|
|
||||||
[Q]
|
|
||||||
quit
|
|
||||||
.TP
|
|
||||||
[R]
|
|
||||||
rotate image on the right
|
|
||||||
.TP
|
|
||||||
[â–¸]
|
[â–¸]
|
||||||
next image
|
next image
|
||||||
.TP
|
.TP
|
||||||
@@ -45,6 +33,27 @@ first image
|
|||||||
.TP
|
.TP
|
||||||
[â–ľ]
|
[â–ľ]
|
||||||
last image
|
last image
|
||||||
|
.TP
|
||||||
|
[Ctrl+C]
|
||||||
|
copy image to clipboard
|
||||||
|
.TP
|
||||||
|
[D]
|
||||||
|
start slideshow
|
||||||
|
.TP
|
||||||
|
[Esc]
|
||||||
|
actual size
|
||||||
|
.TP
|
||||||
|
[F]
|
||||||
|
toggle full-screen mode
|
||||||
|
.TP
|
||||||
|
[L]
|
||||||
|
rotate image on the left
|
||||||
|
.TP
|
||||||
|
[Q]
|
||||||
|
quit
|
||||||
|
.TP
|
||||||
|
[R]
|
||||||
|
rotate image on the right
|
||||||
.SH AUTHOR
|
.SH AUTHOR
|
||||||
.B wmiv
|
.B wmiv
|
||||||
is a part of Window Maker. It was written by David Maciejak.
|
is a part of Window Maker. It was written by David Maciejak.
|
||||||
|
|||||||
+6
-6
@@ -37,7 +37,7 @@ AC_DEFUN_ONCE([WM_I18N_LANGUAGES],
|
|||||||
[AC_ARG_VAR([LINGUAS],
|
[AC_ARG_VAR([LINGUAS],
|
||||||
[list of language translations to support (I18N), use 'list' to get the list of supported languages, default: none])dnl
|
[list of language translations to support (I18N), use 'list' to get the list of supported languages, default: none])dnl
|
||||||
AC_DEFUN([WM_ALL_LANGUAGES],
|
AC_DEFUN([WM_ALL_LANGUAGES],
|
||||||
[m4_esyscmd([( ls wrlib/po/ ; ls WINGs/po/ ; ls po/ ; ls WPrefs.app/po/ ; ls util/po/ ) | sed -n -e '/po$/{s,\.po,,;p}' | sort -u | tr '\n' ' '])])dnl
|
[m4_esyscmd([( ls wrlib/po/ ; ls WINGs/po/ ; ls po/ ; ls WPrefs.app/po/ ; ls util/po/ ) | sed -n -e '/po$/{s,\.po,,;p;}' | sort -u | tr '\n' ' '])])dnl
|
||||||
dnl We 'divert' the macro to have it executed as soon as the option list have
|
dnl We 'divert' the macro to have it executed as soon as the option list have
|
||||||
dnl been processed, so the list of locales will be printed after the configure
|
dnl been processed, so the list of locales will be printed after the configure
|
||||||
dnl options have been parsed, but before any test have been run
|
dnl options have been parsed, but before any test have been run
|
||||||
@@ -66,11 +66,11 @@ AS_IF([test "x$LINGUAS" != "x"],
|
|||||||
supported_locales=""
|
supported_locales=""
|
||||||
|
|
||||||
# This is the list of locales that our archive currently supports
|
# This is the list of locales that our archive currently supports
|
||||||
wraster_locales=" m4_esyscmd([ls wrlib/po/ | sed -n '/po$/{s,.po,,;p}' | tr '\n' ' '])"
|
wraster_locales=" m4_esyscmd([ls wrlib/po/ | sed -n '/po$/{s,.po,,;p;}' | tr '\n' ' '])"
|
||||||
wings_locales=" m4_esyscmd([ls WINGs/po/ | sed -n '/po$/{s,.po,,;p}' | tr '\n' ' '])"
|
wings_locales=" m4_esyscmd([ls WINGs/po/ | sed -n '/po$/{s,.po,,;p;}' | tr '\n' ' '])"
|
||||||
wmaker_locales=" m4_esyscmd([ls po/ | sed -n '/po$/{s,.po,,;p}' | tr '\n' ' '])"
|
wmaker_locales=" m4_esyscmd([ls po/ | sed -n '/po$/{s,.po,,;p;}' | tr '\n' ' '])"
|
||||||
wprefs_locales=" m4_esyscmd([ls WPrefs.app/po/ | sed -n '/po$/{s,.po,,;p}' | tr '\n' ' '])"
|
wprefs_locales=" m4_esyscmd([ls WPrefs.app/po/ | sed -n '/po$/{s,.po,,;p;}' | tr '\n' ' '])"
|
||||||
util_locales=" m4_esyscmd([ls util/po/ | sed -n '/po$/{s,.po,,;p}' | tr '\n' ' '])"
|
util_locales=" m4_esyscmd([ls util/po/ | sed -n '/po$/{s,.po,,;p;}' | tr '\n' ' '])"
|
||||||
man_locales=" m4_esyscmd([ls doc/ | grep '^[a-z][a-z]\(_[A-Z][A-Z]\)*$' | tr '\n' ' '])"
|
man_locales=" m4_esyscmd([ls doc/ | grep '^[a-z][a-z]\(_[A-Z][A-Z]\)*$' | tr '\n' ' '])"
|
||||||
|
|
||||||
# If the LINGUAS is specified as a simple '*', then we enable all the languages
|
# If the LINGUAS is specified as a simple '*', then we enable all the languages
|
||||||
|
|||||||
@@ -113,6 +113,37 @@ AC_DEFUN_ONCE([WM_IMGFMT_CHECK_JPEG],
|
|||||||
]) dnl AC_DEFUN
|
]) dnl AC_DEFUN
|
||||||
|
|
||||||
|
|
||||||
|
# WM_IMGFMT_CHECK_JXL
|
||||||
|
# -------------------
|
||||||
|
#
|
||||||
|
# Check for JXL (JPEG XL) file support through 'libjxl'
|
||||||
|
# The check depends on variable 'enable_jxl' 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 GFXLIBS, and append info to
|
||||||
|
# the variable 'supported_gfx'
|
||||||
|
# When not found, append info to variable 'unsupported'
|
||||||
|
AC_DEFUN_ONCE([WM_IMGFMT_CHECK_JXL],
|
||||||
|
[WM_LIB_CHECK([JXL], [-ljxl], [JxlDecoderCreate], [$XLFLAGS $XLIBS],
|
||||||
|
[AC_COMPILE_IFELSE(
|
||||||
|
[AC_LANG_PROGRAM(
|
||||||
|
[@%:@include <stdlib.h>
|
||||||
|
@%:@include <jxl/decode.h>],
|
||||||
|
[ JxlDecoder* dec = JxlDecoderCreate(NULL);
|
||||||
|
JxlDecoderDestroy(dec);])],
|
||||||
|
[],
|
||||||
|
[AS_ECHO([failed])
|
||||||
|
AS_ECHO(["$as_me: error: found $CACHEVAR but cannot compile header"])
|
||||||
|
AS_ECHO(["$as_me: error: - does header 'jxl/decode.h' exists? (is package 'libjxl-dev' missing?)"])
|
||||||
|
AS_ECHO(["$as_me: error: - version of header is not supported? (report to dev team)"])
|
||||||
|
AC_MSG_ERROR([JXL library is not usable, cannot continue])])
|
||||||
|
],
|
||||||
|
[supported_gfx], [GFXLIBS])dnl
|
||||||
|
]) dnl AC_DEFUN
|
||||||
|
|
||||||
|
|
||||||
# WM_IMGFMT_CHECK_PNG
|
# WM_IMGFMT_CHECK_PNG
|
||||||
# -------------------
|
# -------------------
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ bs.po Bosnian Ahmet Mulalic <am@lugzdk.ba>
|
|||||||
hy.po Armenian Norayr Chilignaryan <chnorik@gmail.com>
|
hy.po Armenian Norayr Chilignaryan <chnorik@gmail.com>
|
||||||
nl.po Dutch Alwin <translations@ziggo.nl>
|
nl.po Dutch Alwin <translations@ziggo.nl>
|
||||||
fy.po Frisian Alwin <translations@ziggo.nl>
|
fy.po Frisian Alwin <translations@ziggo.nl>
|
||||||
sr.po Serbian Strahinya Radich <contact@strahinja.org>
|
sr.po Serbian Strahinya Radich <sr@strahinja.org>
|
||||||
|
|
||||||
|
|
||||||
Some translations are based on previous translations by other people.
|
Some translations are based on previous translations by other people.
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
# 1998-2006 Dan Pascu
|
# 1998-2006 Dan Pascu
|
||||||
# 2013-2020 Window Maker Developers Team
|
# 2013-2020 Window Maker Developers Team
|
||||||
# This file is distributed under the same license as the Window Maker package.
|
# This file is distributed under the same license as the Window Maker package.
|
||||||
# Strahinya Radich (Страхиња Радић) <contact@strahinja.org>, 2023.
|
# Strahinya Radich (Страхиња Радић) <sr@strahinja.org>, 2023.
|
||||||
#
|
#
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -11,7 +11,7 @@ msgstr ""
|
|||||||
"Report-Msgid-Bugs-To: wmaker-dev@googlegroups.com\n"
|
"Report-Msgid-Bugs-To: wmaker-dev@googlegroups.com\n"
|
||||||
"POT-Creation-Date: 2023-11-02 19:22+0100\n"
|
"POT-Creation-Date: 2023-11-02 19:22+0100\n"
|
||||||
"PO-Revision-Date: 2023-11-02 19:51+0100\n"
|
"PO-Revision-Date: 2023-11-02 19:51+0100\n"
|
||||||
"Last-Translator: Страхиња Радић <contact@strahinja.org>\n"
|
"Last-Translator: Страхиња Радић <sr@strahinja.org>\n"
|
||||||
"Language-Team: Serbian <sr@li.org>\n"
|
"Language-Team: Serbian <sr@li.org>\n"
|
||||||
"Language: sr\n"
|
"Language: sr\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
|
|||||||
+2
-2
@@ -454,6 +454,7 @@ extern struct WPreferences {
|
|||||||
char single_click; /* single click to lauch applications */
|
char single_click; /* single click to lauch applications */
|
||||||
int history_lines; /* history of "Run..." dialog */
|
int history_lines; /* history of "Run..." dialog */
|
||||||
char cycle_active_head_only; /* Cycle only windows on the active head */
|
char cycle_active_head_only; /* Cycle only windows on the active head */
|
||||||
|
char cycle_all_workspaces; /* Cycle all windows from all workspaces */
|
||||||
char cycle_ignore_minimized; /* Ignore minimized windows when cycling */
|
char cycle_ignore_minimized; /* Ignore minimized windows when cycling */
|
||||||
char double_click_fullscreen; /* Double click on titlebar maximize a window to full screen*/
|
char double_click_fullscreen; /* Double click on titlebar maximize a window to full screen*/
|
||||||
char close_rootmenu_left_right_click;/* Close application menu when mouse (left or right) is clicked outside focus */
|
char close_rootmenu_left_right_click;/* Close application menu when mouse (left or right) is clicked outside focus */
|
||||||
@@ -478,6 +479,7 @@ extern struct WPreferences {
|
|||||||
int hot_corner_delay; /* Delay after which the hot corner is triggered */
|
int hot_corner_delay; /* Delay after which the hot corner is triggered */
|
||||||
int hot_corner_edge; /* Hot corner edge size */
|
int hot_corner_edge; /* Hot corner edge size */
|
||||||
char *hot_corner_actions[4]; /* Action of each corner */
|
char *hot_corner_actions[4]; /* Action of each corner */
|
||||||
|
char window_list_app_icons; /* Show app icons in window list */
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
#ifdef USE_ICCCM_WMREPLACE
|
#ifdef USE_ICCCM_WMREPLACE
|
||||||
@@ -618,12 +620,10 @@ extern struct wmaker_global_variables {
|
|||||||
} shape;
|
} shape;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef KEEP_XKB_LOCK_STATUS
|
|
||||||
struct {
|
struct {
|
||||||
Bool supported;
|
Bool supported;
|
||||||
int event_base;
|
int event_base;
|
||||||
} xkb;
|
} xkb;
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef USE_RANDR
|
#ifdef USE_RANDR
|
||||||
struct {
|
struct {
|
||||||
|
|||||||
+9
-6
@@ -1186,14 +1186,17 @@ static void create_appicon_from_dock(WWindow *wwin, WApplication *wapp, Window m
|
|||||||
|
|
||||||
wapp->app_icon->running = 1;
|
wapp->app_icon->running = 1;
|
||||||
wapp->app_icon->icon->owner = mainw;
|
wapp->app_icon->icon->owner = mainw;
|
||||||
if (mainw->wm_hints && (mainw->wm_hints->flags & IconWindowHint))
|
|
||||||
wapp->app_icon->icon->icon_win = mainw->wm_hints->icon_window;
|
|
||||||
|
|
||||||
/* Update the icon images */
|
if (!WFLAGP(wwin, always_user_icon)) {
|
||||||
wIconUpdate(wapp->app_icon->icon);
|
if (mainw->wm_hints && (mainw->wm_hints->flags & IconWindowHint))
|
||||||
|
wapp->app_icon->icon->icon_win = mainw->wm_hints->icon_window;
|
||||||
|
|
||||||
/* Paint it */
|
/* Update the icon images */
|
||||||
wAppIconPaint(wapp->app_icon);
|
wIconUpdate(wapp->app_icon->icon);
|
||||||
|
|
||||||
|
/* Paint it */
|
||||||
|
wAppIconPaint(wapp->app_icon);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+23
-8
@@ -245,6 +245,20 @@ void wClientConfigure(WWindow * wwin, XConfigureRequestEvent * xcre)
|
|||||||
wwin->flags.maximized &= ~(MAX_VERTICAL | MAX_LEFTHALF | MAX_RIGHTHALF | MAX_MAXIMUS | MAX_CENTRAL);
|
wwin->flags.maximized &= ~(MAX_VERTICAL | MAX_LEFTHALF | MAX_RIGHTHALF | MAX_MAXIMUS | MAX_CENTRAL);
|
||||||
|
|
||||||
wWindowConstrainSize(wwin, (unsigned int *)&nwidth, (unsigned int *)&nheight);
|
wWindowConstrainSize(wwin, (unsigned int *)&nwidth, (unsigned int *)&nheight);
|
||||||
|
|
||||||
|
/* Ignore tiny position adjustments from client ConfigureRequests to prevent
|
||||||
|
* window jitters (e.g., VirtualBox sending incremental 1-2px corrections). */
|
||||||
|
if (wwin->flags.mapped && !wwin->moveresize.active && (xcre->value_mask & (CWX | CWY))) {
|
||||||
|
int dx = abs(nx - wwin->frame_x);
|
||||||
|
int dy = abs(ny - wwin->frame_y);
|
||||||
|
|
||||||
|
if (dx < 3 && dy < 3) {
|
||||||
|
/* Keep current position */
|
||||||
|
nx = wwin->frame_x;
|
||||||
|
ny = wwin->frame_y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
wWindowConfigure(wwin, nx, ny, nwidth, nheight);
|
wWindowConfigure(wwin, nx, ny, nwidth, nheight);
|
||||||
wwin->old_geometry.x = nx;
|
wwin->old_geometry.x = nx;
|
||||||
wwin->old_geometry.y = ny;
|
wwin->old_geometry.y = ny;
|
||||||
@@ -454,15 +468,16 @@ void wClientCheckProperty(WWindow * wwin, XPropertyEvent * event)
|
|||||||
/* update icon */
|
/* update icon */
|
||||||
if ((wwin->wm_hints->flags & IconPixmapHint)
|
if ((wwin->wm_hints->flags & IconPixmapHint)
|
||||||
|| (wwin->wm_hints->flags & IconWindowHint)) {
|
|| (wwin->wm_hints->flags & IconWindowHint)) {
|
||||||
WApplication *wapp;
|
if (!WFLAGP(wwin, always_user_icon)) {
|
||||||
|
WApplication *wapp;
|
||||||
|
if (wwin->flags.miniaturized && wwin->icon)
|
||||||
|
wIconUpdate(wwin->icon);
|
||||||
|
|
||||||
if (wwin->flags.miniaturized && wwin->icon)
|
wapp = wApplicationOf(wwin->main_window);
|
||||||
wIconUpdate(wwin->icon);
|
if (wapp && wapp->app_icon) {
|
||||||
|
wIconUpdate(wapp->app_icon->icon);
|
||||||
wapp = wApplicationOf(wwin->main_window);
|
wAppIconPaint(wapp->app_icon);
|
||||||
if (wapp && wapp->app_icon) {
|
}
|
||||||
wIconUpdate(wapp->app_icon->icon);
|
|
||||||
wAppIconPaint(wapp->app_icon);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -534,6 +534,8 @@ WDefaultEntry optionList[] = {
|
|||||||
&wPreferences.hot_corner_edge, getInt, NULL, NULL, NULL},
|
&wPreferences.hot_corner_edge, getInt, NULL, NULL, NULL},
|
||||||
{"HotCornerActions", "(\"None\", \"None\", \"None\", \"None\")", &wPreferences,
|
{"HotCornerActions", "(\"None\", \"None\", \"None\", \"None\")", &wPreferences,
|
||||||
NULL, getPropList, setHotCornerActions, NULL, NULL},
|
NULL, getPropList, setHotCornerActions, NULL, NULL},
|
||||||
|
{"WindowListAppIcons", "NO", NULL,
|
||||||
|
&wPreferences.window_list_app_icons, getBool, NULL, NULL, NULL},
|
||||||
|
|
||||||
/* style options */
|
/* style options */
|
||||||
|
|
||||||
@@ -849,6 +851,8 @@ WDefaultEntry optionList[] = {
|
|||||||
&wPreferences.history_lines, getInt, NULL, NULL, NULL},
|
&wPreferences.history_lines, getInt, NULL, NULL, NULL},
|
||||||
{"CycleActiveHeadOnly", "NO", NULL,
|
{"CycleActiveHeadOnly", "NO", NULL,
|
||||||
&wPreferences.cycle_active_head_only, getBool, NULL, NULL, NULL},
|
&wPreferences.cycle_active_head_only, getBool, NULL, NULL, NULL},
|
||||||
|
{"CycleAllWorkspaces", "NO", NULL,
|
||||||
|
&wPreferences.cycle_all_workspaces, getBool, NULL, NULL, NULL},
|
||||||
{"CycleIgnoreMinimized", "NO", NULL,
|
{"CycleIgnoreMinimized", "NO", NULL,
|
||||||
&wPreferences.cycle_ignore_minimized, getBool, NULL, NULL, NULL},
|
&wPreferences.cycle_ignore_minimized, getBool, NULL, NULL, NULL},
|
||||||
{"DbClickFullScreen", "NO", NULL,
|
{"DbClickFullScreen", "NO", NULL,
|
||||||
@@ -1301,6 +1305,29 @@ void wReadDefaults(WScreen * scr, WMPropList * new_dict)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void wReadKeybindings(WScreen *scr, WMPropList *dict)
|
||||||
|
{
|
||||||
|
WDefaultEntry *entry;
|
||||||
|
unsigned int i;
|
||||||
|
void *tdata;
|
||||||
|
|
||||||
|
for (i = 0; i < wlengthof(optionList); i++) {
|
||||||
|
entry = &optionList[i];
|
||||||
|
if (entry->convert == getKeybind) {
|
||||||
|
WMPropList *plvalue = NULL;
|
||||||
|
if (dict)
|
||||||
|
plvalue = WMGetFromPLDictionary(dict, entry->plkey);
|
||||||
|
if (!plvalue)
|
||||||
|
plvalue = entry->plvalue;
|
||||||
|
if (plvalue) {
|
||||||
|
int ok = (*entry->convert)(scr, entry, plvalue, entry->addr, &tdata);
|
||||||
|
if (ok && entry->update)
|
||||||
|
(*entry->update)(scr, entry, tdata, entry->extra_data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void wDefaultUpdateIcons(WScreen *scr)
|
void wDefaultUpdateIcons(WScreen *scr)
|
||||||
{
|
{
|
||||||
WAppIcon *aicon = scr->app_icon_list;
|
WAppIcon *aicon = scr->app_icon_list;
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ WDDomain * wDefaultsInitDomain(const char *domain, Bool requireDictionary);
|
|||||||
void wDefaultsMergeGlobalMenus(WDDomain *menuDomain);
|
void wDefaultsMergeGlobalMenus(WDDomain *menuDomain);
|
||||||
|
|
||||||
void wReadDefaults(WScreen *scr, WMPropList *new_dict);
|
void wReadDefaults(WScreen *scr, WMPropList *new_dict);
|
||||||
|
void wReadKeybindings(WScreen *scr, WMPropList *dict);
|
||||||
void wDefaultUpdateIcons(WScreen *scr);
|
void wDefaultUpdateIcons(WScreen *scr);
|
||||||
void wReadStaticDefaults(WMPropList *dict);
|
void wReadStaticDefaults(WMPropList *dict);
|
||||||
void wDefaultsCheckDomains(void *arg);
|
void wDefaultsCheckDomains(void *arg);
|
||||||
|
|||||||
+22
-6
@@ -1083,6 +1083,7 @@ Bool wIconChooserDialog(WScreen *scr, char **file, const char *instance, const c
|
|||||||
WMMapWidget(panel->win);
|
WMMapWidget(panel->win);
|
||||||
|
|
||||||
wWindowMap(wwin);
|
wWindowMap(wwin);
|
||||||
|
wSetFocusTo(scr, wwin);
|
||||||
|
|
||||||
while (!panel->done) {
|
while (!panel->done) {
|
||||||
XEvent event;
|
XEvent event;
|
||||||
@@ -1276,9 +1277,9 @@ void wShowInfoPanel(WScreen *scr)
|
|||||||
panel->win = WMCreateWindow(scr->wmscreen, "info");
|
panel->win = WMCreateWindow(scr->wmscreen, "info");
|
||||||
WMGetScaleBaseFromSystemFont(scr->wmscreen, &wmScaleWidth, &wmScaleHeight);
|
WMGetScaleBaseFromSystemFont(scr->wmscreen, &wmScaleWidth, &wmScaleHeight);
|
||||||
#if defined(HAVE_MALLOC_H) && defined(HAVE_MALLINFO2) && defined(DEBUG)
|
#if defined(HAVE_MALLOC_H) && defined(HAVE_MALLINFO2) && defined(DEBUG)
|
||||||
pwidth = WMScaleX(412);
|
pwidth = WMScaleX(432);
|
||||||
#else
|
#else
|
||||||
pwidth = WMScaleX(382);
|
pwidth = WMScaleX(392);
|
||||||
#endif
|
#endif
|
||||||
pheight = WMScaleY(270);
|
pheight = WMScaleY(270);
|
||||||
WMResizeWidget(panel->win, pwidth, pheight);
|
WMResizeWidget(panel->win, pwidth, pheight);
|
||||||
@@ -1344,7 +1345,7 @@ void wShowInfoPanel(WScreen *scr)
|
|||||||
|
|
||||||
panel->copyrL = WMCreateLabel(panel->win);
|
panel->copyrL = WMCreateLabel(panel->win);
|
||||||
WMResizeWidget(panel->copyrL, WMScaleX(360), WMScaleY(60));
|
WMResizeWidget(panel->copyrL, WMScaleX(360), WMScaleY(60));
|
||||||
WMMoveWidget(panel->copyrL, WMScaleX(15), WMScaleY(210));
|
WMMoveWidget(panel->copyrL, WMScaleX(15), WMScaleY(215));
|
||||||
WMSetLabelTextAlignment(panel->copyrL, WALeft);
|
WMSetLabelTextAlignment(panel->copyrL, WALeft);
|
||||||
|
|
||||||
snprintf(buffer, sizeof(buffer), COPYRIGHT_TEXT, current_year);
|
snprintf(buffer, sizeof(buffer), COPYRIGHT_TEXT, current_year);
|
||||||
@@ -1455,7 +1456,7 @@ void wShowInfoPanel(WScreen *scr)
|
|||||||
strbuf = wstrappend(strbuf, _("Xinerama: "));
|
strbuf = wstrappend(strbuf, _("Xinerama: "));
|
||||||
{
|
{
|
||||||
char tmp[128];
|
char tmp[128];
|
||||||
snprintf(tmp, sizeof(tmp) - 1, _("%d head(s) found"), scr->xine_info.count);
|
snprintf(tmp, sizeof(tmp) - 1, scr->xine_info.count > 1 ? _("%d head(s) found") : _("%d head found"), scr->xine_info.count);
|
||||||
strbuf = wstrappend(strbuf, tmp);
|
strbuf = wstrappend(strbuf, tmp);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -1471,9 +1472,9 @@ void wShowInfoPanel(WScreen *scr)
|
|||||||
|
|
||||||
panel->infoL = WMCreateLabel(panel->win);
|
panel->infoL = WMCreateLabel(panel->win);
|
||||||
#if defined(HAVE_MALLOC_H) && defined(HAVE_MALLINFO2) && defined(DEBUG)
|
#if defined(HAVE_MALLOC_H) && defined(HAVE_MALLINFO2) && defined(DEBUG)
|
||||||
WMResizeWidget(panel->infoL, WMScaleX(380), WMScaleY(100));
|
WMResizeWidget(panel->infoL, WMScaleX(430), WMScaleY(105));
|
||||||
#else
|
#else
|
||||||
WMResizeWidget(panel->infoL, WMScaleX(350), WMScaleY(100));
|
WMResizeWidget(panel->infoL, WMScaleX(370), WMScaleY(105));
|
||||||
#endif
|
#endif
|
||||||
WMMoveWidget(panel->infoL, WMScaleX(15), WMScaleY(115));
|
WMMoveWidget(panel->infoL, WMScaleX(15), WMScaleY(115));
|
||||||
WMSetLabelText(panel->infoL, strbuf);
|
WMSetLabelText(panel->infoL, strbuf);
|
||||||
@@ -1641,6 +1642,8 @@ typedef struct _CrashPanel {
|
|||||||
int action; /* what to do after */
|
int action; /* what to do after */
|
||||||
|
|
||||||
KeyCode retKey;
|
KeyCode retKey;
|
||||||
|
KeyCode upKey;
|
||||||
|
KeyCode downKey;
|
||||||
|
|
||||||
} CrashPanel;
|
} CrashPanel;
|
||||||
|
|
||||||
@@ -1650,6 +1653,17 @@ static void handleKeyPress(XEvent * event, void *clientData)
|
|||||||
|
|
||||||
if (event->xkey.keycode == panel->retKey) {
|
if (event->xkey.keycode == panel->retKey) {
|
||||||
WMPerformButtonClick(panel->okB);
|
WMPerformButtonClick(panel->okB);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event->xkey.keycode == panel->upKey) {
|
||||||
|
WMSelectPopUpButtonPreviousItem(panel->whatP);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event->xkey.keycode == panel->downKey) {
|
||||||
|
WMSelectPopUpButtonNextItem(panel->whatP);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1721,6 +1735,8 @@ int wShowCrashingDialogPanel(int whatSig)
|
|||||||
panel = wmalloc(sizeof(CrashPanel));
|
panel = wmalloc(sizeof(CrashPanel));
|
||||||
|
|
||||||
panel->retKey = XKeysymToKeycode(dpy, XK_Return);
|
panel->retKey = XKeysymToKeycode(dpy, XK_Return);
|
||||||
|
panel->upKey = XKeysymToKeycode(dpy, XK_Up);
|
||||||
|
panel->downKey = XKeysymToKeycode(dpy, XK_Down);
|
||||||
|
|
||||||
panel->win = WMCreateWindow(scr, "crashingDialog");
|
panel->win = WMCreateWindow(scr, "crashingDialog");
|
||||||
WMResizeWidget(panel->win, PWIDTH, PHEIGHT);
|
WMResizeWidget(panel->win, PWIDTH, PHEIGHT);
|
||||||
|
|||||||
+41
-10
@@ -49,9 +49,7 @@
|
|||||||
#include <X11/extensions/Xrandr.h>
|
#include <X11/extensions/Xrandr.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef KEEP_XKB_LOCK_STATUS
|
|
||||||
#include <X11/XKBlib.h>
|
#include <X11/XKBlib.h>
|
||||||
#endif /* KEEP_XKB_LOCK_STATUS */
|
|
||||||
|
|
||||||
#include "WindowMaker.h"
|
#include "WindowMaker.h"
|
||||||
#include "window.h"
|
#include "window.h"
|
||||||
@@ -103,7 +101,9 @@ static void handleKeyPress(XEvent *event);
|
|||||||
static void handleFocusIn(XEvent *event);
|
static void handleFocusIn(XEvent *event);
|
||||||
static void handleMotionNotify(XEvent *event);
|
static void handleMotionNotify(XEvent *event);
|
||||||
static void handleVisibilityNotify(XEvent *event);
|
static void handleVisibilityNotify(XEvent *event);
|
||||||
|
#ifdef HAVE_INOTIFY
|
||||||
static void handle_inotify_events(void);
|
static void handle_inotify_events(void);
|
||||||
|
#endif
|
||||||
static void handle_selection_request(XSelectionRequestEvent *event);
|
static void handle_selection_request(XSelectionRequestEvent *event);
|
||||||
static void handle_selection_clear(XSelectionClearEvent *event);
|
static void handle_selection_clear(XSelectionClearEvent *event);
|
||||||
static void wdelete_death_handler(WMagicNumber id);
|
static void wdelete_death_handler(WMagicNumber id);
|
||||||
@@ -569,11 +569,26 @@ static void handleExtensions(XEvent * event)
|
|||||||
handleShapeNotify(event);
|
handleShapeNotify(event);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
if (w_global.xext.xkb.supported && event->type == w_global.xext.xkb.event_base) {
|
||||||
|
XkbEvent *xkbevent = (XkbEvent *) event;
|
||||||
|
|
||||||
|
if (xkbevent->any.xkb_type == XkbNewKeyboardNotify) {
|
||||||
|
int j;
|
||||||
|
WScreen *scr;
|
||||||
|
|
||||||
|
for (j = 0; j < w_global.screen_count; j++) {
|
||||||
|
scr = wScreenWithNumber(j);
|
||||||
|
wReadKeybindings(scr, w_global.domain.wmaker->dictionary);
|
||||||
|
}
|
||||||
|
}
|
||||||
#ifdef KEEP_XKB_LOCK_STATUS
|
#ifdef KEEP_XKB_LOCK_STATUS
|
||||||
if (wPreferences.modelock && (event->type == w_global.xext.xkb.event_base)) {
|
else {
|
||||||
handleXkbIndicatorStateNotify((XkbEvent *) event);
|
if (wPreferences.modelock && (xkbevent->any.xkb_type == XkbIndicatorStateNotify)) {
|
||||||
|
handleXkbIndicatorStateNotify((XkbEvent *) event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /*KEEP_XKB_LOCK_STATUS */
|
||||||
}
|
}
|
||||||
#endif /*KEEP_XKB_LOCK_STATUS */
|
|
||||||
#ifdef USE_RANDR
|
#ifdef USE_RANDR
|
||||||
if (w_global.xext.randr.supported && event->type == (w_global.xext.randr.event_base + RRScreenChangeNotify)) {
|
if (w_global.xext.randr.supported && event->type == (w_global.xext.randr.event_base + RRScreenChangeNotify)) {
|
||||||
/* From xrandr man page: "Clients must call back into Xlib using
|
/* From xrandr man page: "Clients must call back into Xlib using
|
||||||
@@ -1275,6 +1290,7 @@ static void handleXkbIndicatorStateNotify(XkbEvent *event)
|
|||||||
WScreen *scr;
|
WScreen *scr;
|
||||||
XkbStateRec staterec;
|
XkbStateRec staterec;
|
||||||
int i;
|
int i;
|
||||||
|
(void) event;
|
||||||
|
|
||||||
for (i = 0; i < w_global.screen_count; i++) {
|
for (i = 0; i < w_global.screen_count; i++) {
|
||||||
scr = wScreenWithNumber(i);
|
scr = wScreenWithNumber(i);
|
||||||
@@ -1942,16 +1958,31 @@ static void handleKeyPress(XEvent * event)
|
|||||||
#define CORNER_BOTTOMLEFT 3
|
#define CORNER_BOTTOMLEFT 3
|
||||||
#define CORNER_BOTTOMRIGHT 4
|
#define CORNER_BOTTOMRIGHT 4
|
||||||
|
|
||||||
static int get_corner(WMRect rect, WMPoint p)
|
static inline int get_corner(WMRect rect, WMPoint p)
|
||||||
{
|
{
|
||||||
if (p.x <= (rect.pos.x + wPreferences.hot_corner_edge) && p.y <= (rect.pos.y + wPreferences.hot_corner_edge))
|
const int edge = wPreferences.hot_corner_edge;
|
||||||
|
const int left_edge = rect.pos.x + edge;
|
||||||
|
const int right_edge = rect.pos.x + rect.size.width - edge;
|
||||||
|
const int top_edge = rect.pos.y + edge;
|
||||||
|
const int bottom_edge = rect.pos.y + rect.size.height - edge;
|
||||||
|
|
||||||
|
int in_left = (p.x <= left_edge);
|
||||||
|
int in_right = (p.x >= right_edge);
|
||||||
|
int in_top = (p.y <= top_edge);
|
||||||
|
int in_bottom = (p.y >= bottom_edge);
|
||||||
|
|
||||||
|
if (!(in_left || in_right) || !(in_top || in_bottom))
|
||||||
|
return CORNER_NONE;
|
||||||
|
|
||||||
|
if (in_left && in_top)
|
||||||
return CORNER_TOPLEFT;
|
return CORNER_TOPLEFT;
|
||||||
if (p.x >= (rect.pos.x + rect.size.width - wPreferences.hot_corner_edge) && p.y <= (rect.pos.y + wPreferences.hot_corner_edge))
|
if (in_right && in_top)
|
||||||
return CORNER_TOPRIGHT;
|
return CORNER_TOPRIGHT;
|
||||||
if (p.x <= (rect.pos.x + wPreferences.hot_corner_edge) && p.y >= (rect.pos.y + rect.size.height - wPreferences.hot_corner_edge))
|
if (in_left && in_bottom)
|
||||||
return CORNER_BOTTOMLEFT;
|
return CORNER_BOTTOMLEFT;
|
||||||
if (p.x >= (rect.pos.x + rect.size.width - wPreferences.hot_corner_edge) && p.y >= (rect.pos.y + rect.size.height - wPreferences.hot_corner_edge))
|
if (in_right && in_bottom)
|
||||||
return CORNER_BOTTOMRIGHT;
|
return CORNER_BOTTOMRIGHT;
|
||||||
|
|
||||||
return CORNER_NONE;
|
return CORNER_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+7
-7
@@ -58,14 +58,14 @@ static void paintButton(WCoreWindow * button, WTexture * texture,
|
|||||||
|
|
||||||
static void updateTitlebar(WFrameWindow * fwin);
|
static void updateTitlebar(WFrameWindow * fwin);
|
||||||
|
|
||||||
static void allocFrameBorderPixel(Colormap colormap, const char *color_name, unsigned long **pixel);
|
static void allocFrameBorderPixel(WFrameWindow *fwin, const char *color_name, unsigned long **pixel);
|
||||||
|
|
||||||
static void allocFrameBorderPixel(Colormap colormap, const char *color_name, unsigned long **pixel) {
|
static void allocFrameBorderPixel(WFrameWindow *fwin, const char *color_name, unsigned long **pixel) {
|
||||||
XColor xcol;
|
XColor xcol;
|
||||||
|
|
||||||
*pixel = NULL;
|
*pixel = NULL;
|
||||||
|
|
||||||
if (! wGetColorForColormap(colormap, color_name, &xcol))
|
if (! wGetColorForColormap(fwin->screen_ptr, fwin->colormap, color_name, &xcol))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
*pixel = wmalloc(sizeof(unsigned long));
|
*pixel = wmalloc(sizeof(unsigned long));
|
||||||
@@ -412,9 +412,9 @@ void wFrameWindowUpdateBorders(WFrameWindow * fwin, int flags)
|
|||||||
|
|
||||||
checkTitleSize(fwin);
|
checkTitleSize(fwin);
|
||||||
|
|
||||||
allocFrameBorderPixel(fwin->colormap, WMGetColorRGBDescription(scr->frame_border_color), &fwin->border_pixel);
|
allocFrameBorderPixel(fwin, WMGetColorRGBDescription(scr->frame_border_color), &fwin->border_pixel);
|
||||||
allocFrameBorderPixel(fwin->colormap, WMGetColorRGBDescription(scr->frame_focused_border_color), &fwin->focused_border_pixel);
|
allocFrameBorderPixel(fwin, WMGetColorRGBDescription(scr->frame_focused_border_color), &fwin->focused_border_pixel);
|
||||||
allocFrameBorderPixel(fwin->colormap, WMGetColorRGBDescription(scr->frame_selected_border_color), &fwin->selected_border_pixel);
|
allocFrameBorderPixel(fwin, WMGetColorRGBDescription(scr->frame_selected_border_color), &fwin->selected_border_pixel);
|
||||||
|
|
||||||
if (flags & WFF_SELECTED) {
|
if (flags & WFF_SELECTED) {
|
||||||
if (fwin->selected_border_pixel)
|
if (fwin->selected_border_pixel)
|
||||||
@@ -1394,7 +1394,7 @@ static void handleButtonExpose(WObjDescriptor * desc, XEvent * event)
|
|||||||
|
|
||||||
#ifdef XKB_BUTTON_HINT
|
#ifdef XKB_BUTTON_HINT
|
||||||
if (button == fwin->language_button) {
|
if (button == fwin->language_button) {
|
||||||
if (wPreferences.modelock)
|
if (!fwin->flags.hide_language_button)
|
||||||
paintButton(button, fwin->title_texture[fwin->flags.state],
|
paintButton(button, fwin->title_texture[fwin->flags.state],
|
||||||
WMColorPixel(fwin->title_color[fwin->flags.state]),
|
WMColorPixel(fwin->title_color[fwin->flags.state]),
|
||||||
fwin->languagebutton_image, False);
|
fwin->languagebutton_image, False);
|
||||||
|
|||||||
@@ -331,6 +331,14 @@ void wIconChangeTitle(WIcon *icon, WWindow *wwin)
|
|||||||
/* Set the new one, using two methods to identify
|
/* Set the new one, using two methods to identify
|
||||||
the icon name or switch back to window name */
|
the icon name or switch back to window name */
|
||||||
icon->icon_name = wNETWMGetIconName(wwin->client_win);
|
icon->icon_name = wNETWMGetIconName(wwin->client_win);
|
||||||
|
if (icon->icon_name) {
|
||||||
|
/* treat empty string as unset */
|
||||||
|
if (icon->icon_name[0] == '\0') {
|
||||||
|
XFree(icon->icon_name);
|
||||||
|
icon->icon_name = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!icon->icon_name)
|
if (!icon->icon_name)
|
||||||
if (!wGetIconName(dpy, wwin->client_win, &icon->icon_name))
|
if (!wGetIconName(dpy, wwin->client_win, &icon->icon_name))
|
||||||
icon->icon_name = wNETWMGetWindowName(wwin->client_win);
|
icon->icon_name = wNETWMGetWindowName(wwin->client_win);
|
||||||
|
|||||||
+6
-4
@@ -326,7 +326,8 @@ void ExecuteShellCommand(WScreen *scr, const char *command)
|
|||||||
#endif
|
#endif
|
||||||
execl(shell, shell, "-c", command, NULL);
|
execl(shell, shell, "-c", command, NULL);
|
||||||
werror("could not execute %s -c %s", shell, command);
|
werror("could not execute %s -c %s", shell, command);
|
||||||
Exit(-1);
|
/* exec failed in child -- exit immediately without running parent cleanup */
|
||||||
|
_exit(127);
|
||||||
} else if (pid < 0) {
|
} else if (pid < 0) {
|
||||||
werror("cannot fork a new process");
|
werror("cannot fork a new process");
|
||||||
} else {
|
} else {
|
||||||
@@ -377,10 +378,10 @@ Bool RelaunchWindow(WWindow *wwin)
|
|||||||
setsid();
|
setsid();
|
||||||
#endif
|
#endif
|
||||||
/* argv is not null-terminated */
|
/* argv is not null-terminated */
|
||||||
char **a = (char **) malloc(argc + 1);
|
char **a = malloc((argc + 1) * sizeof(char *));
|
||||||
if (! a) {
|
if (! a) {
|
||||||
werror("out of memory trying to relaunch the application");
|
werror("out of memory trying to relaunch the application");
|
||||||
Exit(-1);
|
_exit(127);
|
||||||
}
|
}
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
@@ -389,7 +390,8 @@ Bool RelaunchWindow(WWindow *wwin)
|
|||||||
a[i] = NULL;
|
a[i] = NULL;
|
||||||
|
|
||||||
execvp(a[0], a);
|
execvp(a[0], a);
|
||||||
Exit(-1);
|
/* exec failed in child -- exit immediately */
|
||||||
|
_exit(127);
|
||||||
} else if (pid < 0) {
|
} else if (pid < 0) {
|
||||||
werror("cannot fork a new process");
|
werror("cannot fork a new process");
|
||||||
|
|
||||||
|
|||||||
+31
@@ -267,6 +267,7 @@ WMenuEntry *wMenuInsertCallback(WMenu *menu, int index, const char *text,
|
|||||||
entry = wmalloc(sizeof(WMenuEntry));
|
entry = wmalloc(sizeof(WMenuEntry));
|
||||||
entry->flags.enabled = 1;
|
entry->flags.enabled = 1;
|
||||||
entry->text = wstrdup(text);
|
entry->text = wstrdup(text);
|
||||||
|
entry->icon = NULL;
|
||||||
entry->cascade = -1;
|
entry->cascade = -1;
|
||||||
entry->clientdata = clientdata;
|
entry->clientdata = clientdata;
|
||||||
entry->callback = callback;
|
entry->callback = callback;
|
||||||
@@ -369,6 +370,9 @@ void wMenuRemoveItem(WMenu * menu, int index)
|
|||||||
if (menu->entries[index]->text)
|
if (menu->entries[index]->text)
|
||||||
wfree(menu->entries[index]->text);
|
wfree(menu->entries[index]->text);
|
||||||
|
|
||||||
|
if (menu->entries[index]->icon)
|
||||||
|
wPixmapDestroy(menu->entries[index]->icon);
|
||||||
|
|
||||||
if (menu->entries[index]->rtext)
|
if (menu->entries[index]->rtext)
|
||||||
wfree(menu->entries[index]->rtext);
|
wfree(menu->entries[index]->rtext);
|
||||||
|
|
||||||
@@ -499,6 +503,10 @@ void wMenuRealize(WMenu * menu)
|
|||||||
text = menu->entries[i]->text;
|
text = menu->entries[i]->text;
|
||||||
width = WMWidthOfString(scr->menu_entry_font, text, strlen(text)) + 10;
|
width = WMWidthOfString(scr->menu_entry_font, text, strlen(text)) + 10;
|
||||||
|
|
||||||
|
if (wPreferences.window_list_app_icons && menu->entries[i]->icon) {
|
||||||
|
width += menu->entries[i]->icon->width + 4;
|
||||||
|
}
|
||||||
|
|
||||||
if (menu->entries[i]->flags.indicator) {
|
if (menu->entries[i]->flags.indicator) {
|
||||||
width += MENU_INDICATOR_SPACE;
|
width += MENU_INDICATOR_SPACE;
|
||||||
}
|
}
|
||||||
@@ -562,6 +570,9 @@ void wMenuDestroy(WMenu * menu, int recurse)
|
|||||||
|
|
||||||
wfree(menu->entries[i]->text);
|
wfree(menu->entries[i]->text);
|
||||||
|
|
||||||
|
if (menu->entries[i]->icon)
|
||||||
|
wPixmapDestroy(menu->entries[i]->icon);
|
||||||
|
|
||||||
if (menu->entries[i]->rtext)
|
if (menu->entries[i]->rtext)
|
||||||
wfree(menu->entries[i]->rtext);
|
wfree(menu->entries[i]->rtext);
|
||||||
#ifdef USER_MENU
|
#ifdef USER_MENU
|
||||||
@@ -711,6 +722,26 @@ static void paintEntry(WMenu * menu, int index, int selected)
|
|||||||
if (entry->flags.indicator)
|
if (entry->flags.indicator)
|
||||||
x += MENU_INDICATOR_SPACE + 2;
|
x += MENU_INDICATOR_SPACE + 2;
|
||||||
|
|
||||||
|
if (wPreferences.window_list_app_icons && entry->icon && entry->icon->image != None) {
|
||||||
|
int ix = x;
|
||||||
|
int iy = y + (h - entry->icon->height) / 2;
|
||||||
|
|
||||||
|
if (entry->icon->mask != None) {
|
||||||
|
XSetClipMask(dpy, scr->copy_gc, entry->icon->mask);
|
||||||
|
XSetClipOrigin(dpy, scr->copy_gc, ix, iy);
|
||||||
|
} else {
|
||||||
|
XSetClipMask(dpy, scr->copy_gc, None);
|
||||||
|
XSetClipOrigin(dpy, scr->copy_gc, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
XCopyArea(dpy, entry->icon->image, win, scr->copy_gc,
|
||||||
|
0, 0, entry->icon->width, entry->icon->height, ix, iy);
|
||||||
|
XSetClipMask(dpy, scr->copy_gc, None);
|
||||||
|
XSetClipOrigin(dpy, scr->copy_gc, 0, 0);
|
||||||
|
|
||||||
|
x += entry->icon->width + 4;
|
||||||
|
}
|
||||||
|
|
||||||
WMDrawString(scr->wmscreen, win, color, scr->menu_entry_font,
|
WMDrawString(scr->wmscreen, win, color, scr->menu_entry_font,
|
||||||
x, 3 + y + wPreferences.menu_text_clearance, entry->text, strlen(entry->text));
|
x, 3 + y + wPreferences.menu_text_clearance, entry->text, strlen(entry->text));
|
||||||
|
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ typedef struct WMenuEntry {
|
|||||||
int order;
|
int order;
|
||||||
char *text; /* entry text */
|
char *text; /* entry text */
|
||||||
char *rtext; /* text to show in the right part */
|
char *rtext; /* text to show in the right part */
|
||||||
|
struct WPixmap *icon; /* optional icon displayed before the text */
|
||||||
void (*callback)(struct WMenu *menu, struct WMenuEntry *entry);
|
void (*callback)(struct WMenu *menu, struct WMenuEntry *entry);
|
||||||
void (*free_cdata)(void *data); /* proc to be used to free clientdata */
|
void (*free_cdata)(void *data); /* proc to be used to free clientdata */
|
||||||
void *clientdata; /* data to pass to callback */
|
void *clientdata; /* data to pass to callback */
|
||||||
|
|||||||
+71
-8
@@ -124,6 +124,44 @@ Bool wGetIconName(Display *dpy, Window win, char **iconname)
|
|||||||
return False;
|
return False;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int WMStrEqual(const char *x, const char *y)
|
||||||
|
{
|
||||||
|
if ((x == NULL) && (y == NULL))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if ((x == NULL) || (y == NULL))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return (strcmp(x, y) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int WMPLGetBool(WMPropList *value)
|
||||||
|
{
|
||||||
|
char *val;
|
||||||
|
|
||||||
|
if (!WMIsPLString(value))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
val = WMGetFromPLString(value);
|
||||||
|
if (val == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if ((val[1] == '\0' &&
|
||||||
|
(val[0] == 'y' || val[0] == 'Y' || val[0] == 'T' ||
|
||||||
|
val[0] == 't' || val[0] == '1')) ||
|
||||||
|
(strcasecmp(val, "YES") == 0 || strcasecmp(val, "TRUE") == 0)) {
|
||||||
|
return 1;
|
||||||
|
} else if ((val[1] == '\0' &&
|
||||||
|
(val[0] == 'n' || val[0] == 'N' || val[0] == 'F' ||
|
||||||
|
val[0] == 'f' || val[0] == '0')) ||
|
||||||
|
(strcasecmp(val, "NO") == 0 || strcasecmp(val, "FALSE") == 0)) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
wwarning(_("can't convert \"%s\" to boolean"), val);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void eatExpose(void)
|
static void eatExpose(void)
|
||||||
{
|
{
|
||||||
XEvent event, foo;
|
XEvent event, foo;
|
||||||
@@ -259,13 +297,22 @@ void slide_windows(Window wins[], int n, int from_x, int from_y, int to_x, int t
|
|||||||
eatExpose();
|
eatExpose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* find the start of a UTF-8 character at or before the given position */
|
||||||
|
static int utf8_find_char_start(const char *string, int pos)
|
||||||
|
{
|
||||||
|
while (pos > 0 && (string[pos] & 0xC0) == 0x80) {
|
||||||
|
pos--;
|
||||||
|
}
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|
||||||
char *ShrinkString(WMFont *font, const char *string, int width)
|
char *ShrinkString(WMFont *font, const char *string, int width)
|
||||||
{
|
{
|
||||||
int w, w1 = 0;
|
int w, w1 = 0;
|
||||||
int p;
|
int p;
|
||||||
char *pos;
|
char *pos;
|
||||||
char *text;
|
char *text;
|
||||||
int p1, p2, t;
|
int p1, p2, t, utf8_safe_pos;
|
||||||
|
|
||||||
p = strlen(string);
|
p = strlen(string);
|
||||||
w = WMWidthOfString(font, string, p);
|
w = WMWidthOfString(font, string, p);
|
||||||
@@ -302,18 +349,34 @@ char *ShrinkString(WMFont *font, const char *string, int width)
|
|||||||
p1 = 0;
|
p1 = 0;
|
||||||
p2 = p;
|
p2 = p;
|
||||||
t = (p2 - p1) / 2;
|
t = (p2 - p1) / 2;
|
||||||
while (p2 > p1 && p1 != t) {
|
while (p2 > p1) {
|
||||||
w = WMWidthOfString(font, &string[p - t], t);
|
int old_t = t;
|
||||||
|
/* ensure we cut at UTF-8 character boundary */
|
||||||
|
utf8_safe_pos = utf8_find_char_start(string, p - t);
|
||||||
|
t = p - utf8_safe_pos;
|
||||||
|
|
||||||
|
w = WMWidthOfString(font, &string[utf8_safe_pos], t);
|
||||||
if (w > width) {
|
if (w > width) {
|
||||||
p2 = t;
|
p2 = t;
|
||||||
t = p1 + (p2 - p1) / 2;
|
|
||||||
} else if (w < width) {
|
} else if (w < width) {
|
||||||
p1 = t;
|
p1 = t;
|
||||||
t = p1 + (p2 - p1) / 2;
|
} else {
|
||||||
} else
|
p1 = t;
|
||||||
p2 = p1 = t;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Calculate new t for next iteration */
|
||||||
|
t = p1 + (p2 - p1) / 2;
|
||||||
|
|
||||||
|
/* Prevent infinite loop if we're not making progress */
|
||||||
|
if (t == old_t || (p2 - p1) <= 1) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
strcat(text, &string[p - p1]);
|
|
||||||
|
/* ensure final cut is at UTF-8 character boundary */
|
||||||
|
utf8_safe_pos = utf8_find_char_start(string, p - p1);
|
||||||
|
strcat(text, &string[utf8_safe_pos]);
|
||||||
|
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,4 +54,6 @@ char *GetShortcutKey(WShortKey key);
|
|||||||
char *EscapeWM_CLASS(const char *name, const char *class);
|
char *EscapeWM_CLASS(const char *name, const char *class);
|
||||||
char *StrConcatDot(const char *a, const char *b);
|
char *StrConcatDot(const char *a, const char *b);
|
||||||
char *GetCommandForWindow(Window win);
|
char *GetCommandForWindow(Window win);
|
||||||
|
int WMStrEqual(const char *x, const char *y);
|
||||||
|
int WMPLGetBool(WMPropList *value);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+42
-4
@@ -19,6 +19,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "wconfig.h"
|
#include "wconfig.h"
|
||||||
|
#include "wmspec.h"
|
||||||
|
|
||||||
#include <X11/Xlib.h>
|
#include <X11/Xlib.h>
|
||||||
#include <X11/Xutil.h>
|
#include <X11/Xutil.h>
|
||||||
@@ -1916,7 +1917,7 @@ int wMouseMoveWindow(WWindow * wwin, XEvent * ev)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case ButtonRelease:
|
case ButtonRelease:
|
||||||
if (event.xbutton.button != ev->xbutton.button)
|
if (!wwin->moveresize.active && (event.xbutton.button != ev->xbutton.button))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (started) {
|
if (started) {
|
||||||
@@ -1964,6 +1965,10 @@ int wMouseMoveWindow(WWindow * wwin, XEvent * ev)
|
|||||||
WMUnmapWidget(scr->gview);
|
WMUnmapWidget(scr->gview);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (wwin->moveresize.active) {
|
||||||
|
XUngrabPointer(dpy, CurrentTime);
|
||||||
|
wwin->moveresize.active = 0;
|
||||||
|
}
|
||||||
done = True;
|
done = True;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -2101,8 +2106,13 @@ void wMouseResizeWindow(WWindow * wwin, XEvent * ev)
|
|||||||
wwarning("internal error: tryein");
|
wwarning("internal error: tryein");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
orig_x = ev->xbutton.x_root;
|
if (ev->type == MotionNotify) {
|
||||||
orig_y = ev->xbutton.y_root;
|
orig_x = ev->xmotion.x_root;
|
||||||
|
orig_y = ev->xmotion.y_root;
|
||||||
|
} else {
|
||||||
|
orig_x = ev->xbutton.x_root;
|
||||||
|
orig_y = ev->xbutton.y_root;
|
||||||
|
}
|
||||||
|
|
||||||
started = 0;
|
started = 0;
|
||||||
wUnselectWindows(scr);
|
wUnselectWindows(scr);
|
||||||
@@ -2113,6 +2123,29 @@ void wMouseResizeWindow(WWindow * wwin, XEvent * ev)
|
|||||||
shiftl = XKeysymToKeycode(dpy, XK_Shift_L);
|
shiftl = XKeysymToKeycode(dpy, XK_Shift_L);
|
||||||
shiftr = XKeysymToKeycode(dpy, XK_Shift_R);
|
shiftr = XKeysymToKeycode(dpy, XK_Shift_R);
|
||||||
|
|
||||||
|
if (wwin->moveresize.active) {
|
||||||
|
int direction = wwin->moveresize.resize_edge;
|
||||||
|
|
||||||
|
res = 0;
|
||||||
|
is_resizebar = 0;
|
||||||
|
if (direction == _NET_WM_MOVERESIZE_SIZE_TOP)
|
||||||
|
res |= UP;
|
||||||
|
else if (direction == _NET_WM_MOVERESIZE_SIZE_BOTTOM)
|
||||||
|
res |= DOWN;
|
||||||
|
else if (direction == _NET_WM_MOVERESIZE_SIZE_LEFT)
|
||||||
|
res |= LEFT;
|
||||||
|
else if (direction == _NET_WM_MOVERESIZE_SIZE_RIGHT)
|
||||||
|
res |= RIGHT;
|
||||||
|
else if (direction == _NET_WM_MOVERESIZE_SIZE_TOPLEFT)
|
||||||
|
res |= (UP | LEFT);
|
||||||
|
else if (direction == _NET_WM_MOVERESIZE_SIZE_TOPRIGHT)
|
||||||
|
res |= (UP | RIGHT);
|
||||||
|
else if (direction == _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT)
|
||||||
|
res |= (DOWN | LEFT);
|
||||||
|
else if (direction == _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT)
|
||||||
|
res |= (DOWN | RIGHT);
|
||||||
|
}
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
WMMaskEvent(dpy, KeyPressMask | ButtonMotionMask
|
WMMaskEvent(dpy, KeyPressMask | ButtonMotionMask
|
||||||
| ButtonReleaseMask | PointerMotionHintMask | ButtonPressMask | ExposureMask, &event);
|
| ButtonReleaseMask | PointerMotionHintMask | ButtonPressMask | ExposureMask, &event);
|
||||||
@@ -2269,7 +2302,7 @@ void wMouseResizeWindow(WWindow * wwin, XEvent * ev)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case ButtonRelease:
|
case ButtonRelease:
|
||||||
if (event.xbutton.button != ev->xbutton.button)
|
if (!wwin->moveresize.active && (event.xbutton.button != ev->xbutton.button))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (started) {
|
if (started) {
|
||||||
@@ -2291,6 +2324,11 @@ void wMouseResizeWindow(WWindow * wwin, XEvent * ev)
|
|||||||
wWindowConfigure(wwin, fx, fy, fw, fh - vert_border);
|
wWindowConfigure(wwin, fx, fy, fw, fh - vert_border);
|
||||||
wWindowSynthConfigureNotify(wwin);
|
wWindowSynthConfigureNotify(wwin);
|
||||||
}
|
}
|
||||||
|
if (wwin->moveresize.active) {
|
||||||
|
XUngrabPointer(dpy, CurrentTime);
|
||||||
|
wwin->moveresize.active = 0;
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|||||||
+2
-2
@@ -197,8 +197,8 @@ void PropSetIconTileHint(WScreen * scr, RImage * image)
|
|||||||
if (image->format == RRGBAFormat) {
|
if (image->format == RRGBAFormat) {
|
||||||
memcpy(&tmp[4], image->data, image->width * image->height * 4);
|
memcpy(&tmp[4], image->data, image->width * image->height * 4);
|
||||||
} else {
|
} else {
|
||||||
char *ptr = (char *)(tmp + 4);
|
unsigned char *ptr = tmp + 4;
|
||||||
char *src = (char *)image->data;
|
unsigned char *src = (unsigned char *)image->data;
|
||||||
|
|
||||||
for (y = 0; y < image->height; y++) {
|
for (y = 0; y < image->height; y++) {
|
||||||
for (x = 0; x < image->width; x++) {
|
for (x = 0; x < image->width; x++) {
|
||||||
|
|||||||
+13
-2
@@ -35,8 +35,16 @@
|
|||||||
#include "resources.h"
|
#include "resources.h"
|
||||||
#include "screen.h"
|
#include "screen.h"
|
||||||
|
|
||||||
int wGetColorForColormap(Colormap colormap, const char *color_name, XColor *color)
|
int wGetColorForColormap(WScreen *scr, Colormap colormap, const char *color_name, XColor *color)
|
||||||
{
|
{
|
||||||
|
if (scr->w_visual->class == TrueColor) {
|
||||||
|
XColor dummy_exact;
|
||||||
|
if (!XLookupColor(dpy, colormap, color_name, &dummy_exact, color)) {
|
||||||
|
wwarning(_("could not lookup color \"%s\""), color_name);
|
||||||
|
return False;
|
||||||
|
}
|
||||||
|
return True;
|
||||||
|
}
|
||||||
if (!XParseColor(dpy, colormap, color_name, color)) {
|
if (!XParseColor(dpy, colormap, color_name, color)) {
|
||||||
wwarning(_("could not parse color \"%s\""), color_name);
|
wwarning(_("could not parse color \"%s\""), color_name);
|
||||||
return False;
|
return False;
|
||||||
@@ -50,11 +58,14 @@ int wGetColorForColormap(Colormap colormap, const char *color_name, XColor *colo
|
|||||||
|
|
||||||
int wGetColor(WScreen *scr, const char *color_name, XColor *color)
|
int wGetColor(WScreen *scr, const char *color_name, XColor *color)
|
||||||
{
|
{
|
||||||
return wGetColorForColormap(scr->w_colormap, color_name, color);
|
return wGetColorForColormap(scr, scr->w_colormap, color_name, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
void wFreeColor(WScreen * scr, unsigned long pixel)
|
void wFreeColor(WScreen * scr, unsigned long pixel)
|
||||||
{
|
{
|
||||||
|
if (scr->w_visual->class == TrueColor)
|
||||||
|
return;
|
||||||
|
|
||||||
if (pixel != scr->white_pixel && pixel != scr->black_pixel) {
|
if (pixel != scr->white_pixel && pixel != scr->black_pixel) {
|
||||||
unsigned long colors[1];
|
unsigned long colors[1];
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -21,7 +21,7 @@
|
|||||||
#ifndef WMRESOURCES_H_
|
#ifndef WMRESOURCES_H_
|
||||||
#define WMRESOURCES_H_
|
#define WMRESOURCES_H_
|
||||||
|
|
||||||
int wGetColorForColormap(Colormap colormap, const char *color_name, XColor *color);
|
int wGetColorForColormap(WScreen *scr, Colormap colormap, const char *color_name, XColor *color);
|
||||||
int wGetColor(WScreen *scr, const char *color_name, XColor *color);
|
int wGetColor(WScreen *scr, const char *color_name, XColor *color);
|
||||||
void wFreeColor(WScreen *scr, unsigned long pixel);
|
void wFreeColor(WScreen *scr, unsigned long pixel);
|
||||||
|
|
||||||
|
|||||||
+5
-9
@@ -32,9 +32,7 @@
|
|||||||
#include <X11/Xlib.h>
|
#include <X11/Xlib.h>
|
||||||
#include <X11/Xutil.h>
|
#include <X11/Xutil.h>
|
||||||
#include <X11/Xatom.h>
|
#include <X11/Xatom.h>
|
||||||
#ifdef KEEP_XKB_LOCK_STATUS
|
|
||||||
#include <X11/XKBlib.h>
|
#include <X11/XKBlib.h>
|
||||||
#endif /* KEEP_XKB_LOCK_STATUS */
|
|
||||||
#ifdef USE_RANDR
|
#ifdef USE_RANDR
|
||||||
#include <X11/extensions/Xrandr.h>
|
#include <X11/extensions/Xrandr.h>
|
||||||
#endif
|
#endif
|
||||||
@@ -663,9 +661,11 @@ WScreen *wScreenInit(int screen_number)
|
|||||||
/* Only GroupLock doesn't work correctly in my system since right-alt
|
/* Only GroupLock doesn't work correctly in my system since right-alt
|
||||||
* can change mode while holding it too - ]d
|
* can change mode while holding it too - ]d
|
||||||
*/
|
*/
|
||||||
if (w_global.xext.xkb.supported) {
|
if (w_global.xext.xkb.supported)
|
||||||
XkbSelectEvents(dpy, XkbUseCoreKbd, XkbStateNotifyMask, XkbStateNotifyMask);
|
XkbSelectEvents(dpy, XkbUseCoreKbd, XkbIndicatorStateNotifyMask|XkbNewKeyboardNotifyMask, XkbIndicatorStateNotifyMask|XkbNewKeyboardNotifyMask);
|
||||||
}
|
#else
|
||||||
|
if (w_global.xext.xkb.supported)
|
||||||
|
XkbSelectEvents(dpy, XkbUseCoreKbd, XkbNewKeyboardNotifyMask, XkbNewKeyboardNotifyMask);
|
||||||
#endif /* KEEP_XKB_LOCK_STATUS */
|
#endif /* KEEP_XKB_LOCK_STATUS */
|
||||||
|
|
||||||
#ifdef USE_RANDR
|
#ifdef USE_RANDR
|
||||||
@@ -1348,11 +1348,7 @@ void ScreenCapture(WScreen *scr, int mode)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (img) {
|
if (img) {
|
||||||
#ifdef USE_PNG
|
|
||||||
if (RSaveTitledImage(img, filepath, (char *)(filetype + 1), "Screenshot from Window Maker")) {
|
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);
|
scale_img = RSmoothScaleImage(img, scr->scr_width / 10, scr->scr_height / 10);
|
||||||
showMiniScreenshot(scr, scale_img);
|
showMiniScreenshot(scr, scale_img);
|
||||||
RReleaseImage(scale_img);
|
RReleaseImage(scale_img);
|
||||||
|
|||||||
+6
-49
@@ -123,35 +123,6 @@ static void make_keys(void)
|
|||||||
sNo = WMCreatePLString("No");
|
sNo = WMCreatePLString("No");
|
||||||
}
|
}
|
||||||
|
|
||||||
static int getBool(WMPropList * value)
|
|
||||||
{
|
|
||||||
char *val;
|
|
||||||
|
|
||||||
if (!WMIsPLString(value)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
val = WMGetFromPLString(value);
|
|
||||||
if (val == NULL)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if ((val[1] == '\0' && (val[0] == 'y' || val[0] == 'Y'))
|
|
||||||
|| strcasecmp(val, "YES") == 0) {
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
} else if ((val[1] == '\0' && (val[0] == 'n' || val[0] == 'N'))
|
|
||||||
|| strcasecmp(val, "NO") == 0) {
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
int i;
|
|
||||||
if (sscanf(val, "%i", &i) == 1) {
|
|
||||||
return (i != 0);
|
|
||||||
} else {
|
|
||||||
wwarning(_("can't convert \"%s\" to boolean"), val);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static unsigned getInt(WMPropList * value)
|
static unsigned getInt(WMPropList * value)
|
||||||
{
|
{
|
||||||
char *val;
|
char *val;
|
||||||
@@ -423,11 +394,11 @@ static WSavedState *getWindowState(WScreen * scr, WMPropList * win_state)
|
|||||||
|
|
||||||
value = WMGetFromPLDictionary(win_state, sShaded);
|
value = WMGetFromPLDictionary(win_state, sShaded);
|
||||||
if (value != NULL)
|
if (value != NULL)
|
||||||
state->shaded = getBool(value);
|
state->shaded = WMPLGetBool(value);
|
||||||
|
|
||||||
value = WMGetFromPLDictionary(win_state, sMiniaturized);
|
value = WMGetFromPLDictionary(win_state, sMiniaturized);
|
||||||
if (value != NULL)
|
if (value != NULL)
|
||||||
state->miniaturized = getBool(value);
|
state->miniaturized = WMPLGetBool(value);
|
||||||
|
|
||||||
value = WMGetFromPLDictionary(win_state, sMaximized);
|
value = WMGetFromPLDictionary(win_state, sMaximized);
|
||||||
if (value != NULL) {
|
if (value != NULL) {
|
||||||
@@ -436,7 +407,7 @@ static WSavedState *getWindowState(WScreen * scr, WMPropList * win_state)
|
|||||||
|
|
||||||
value = WMGetFromPLDictionary(win_state, sHidden);
|
value = WMGetFromPLDictionary(win_state, sHidden);
|
||||||
if (value != NULL)
|
if (value != NULL)
|
||||||
state->hidden = getBool(value);
|
state->hidden = WMPLGetBool(value);
|
||||||
|
|
||||||
value = WMGetFromPLDictionary(win_state, sShortcutMask);
|
value = WMGetFromPLDictionary(win_state, sShortcutMask);
|
||||||
if (value != NULL) {
|
if (value != NULL) {
|
||||||
@@ -456,20 +427,6 @@ static WSavedState *getWindowState(WScreen * scr, WMPropList * win_state)
|
|||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int is_same(const char *x, const char *y)
|
|
||||||
{
|
|
||||||
if ((x == NULL) && (y == NULL))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
if ((x == NULL) || (y == NULL))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (strcmp(x, y) == 0)
|
|
||||||
return 1;
|
|
||||||
else
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void wSessionRestoreState(WScreen *scr)
|
void wSessionRestoreState(WScreen *scr)
|
||||||
{
|
{
|
||||||
WSavedState *state;
|
WSavedState *state;
|
||||||
@@ -556,9 +513,9 @@ void wSessionRestoreState(WScreen *scr)
|
|||||||
if (dock != NULL) {
|
if (dock != NULL) {
|
||||||
for (j = 0; j < dock->max_icons; j++) {
|
for (j = 0; j < dock->max_icons; j++) {
|
||||||
btn = dock->icon_array[j];
|
btn = dock->icon_array[j];
|
||||||
if (btn && is_same(instance, btn->wm_instance) &&
|
if (btn && WMStrEqual(instance, btn->wm_instance) &&
|
||||||
is_same(class, btn->wm_class) &&
|
WMStrEqual(class, btn->wm_class) &&
|
||||||
is_same(command, btn->command) &&
|
WMStrEqual(command, btn->command) &&
|
||||||
!btn->launching) {
|
!btn->launching) {
|
||||||
found = 1;
|
found = 1;
|
||||||
break;
|
break;
|
||||||
|
|||||||
+4
-3
@@ -41,9 +41,7 @@
|
|||||||
#ifdef USE_XSHAPE
|
#ifdef USE_XSHAPE
|
||||||
#include <X11/extensions/shape.h>
|
#include <X11/extensions/shape.h>
|
||||||
#endif
|
#endif
|
||||||
#ifdef KEEP_XKB_LOCK_STATUS
|
|
||||||
#include <X11/XKBlib.h>
|
#include <X11/XKBlib.h>
|
||||||
#endif
|
|
||||||
#ifdef USE_RANDR
|
#ifdef USE_RANDR
|
||||||
#include <X11/extensions/Xrandr.h>
|
#include <X11/extensions/Xrandr.h>
|
||||||
#endif
|
#endif
|
||||||
@@ -601,12 +599,15 @@ void StartUp(Bool defaultScreenOnly)
|
|||||||
w_global.xext.randr.supported = XRRQueryExtension(dpy, &w_global.xext.randr.event_base, &j);
|
w_global.xext.randr.supported = XRRQueryExtension(dpy, &w_global.xext.randr.event_base, &j);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef KEEP_XKB_LOCK_STATUS
|
|
||||||
w_global.xext.xkb.supported = XkbQueryExtension(dpy, NULL, &w_global.xext.xkb.event_base, NULL, NULL, NULL);
|
w_global.xext.xkb.supported = XkbQueryExtension(dpy, NULL, &w_global.xext.xkb.event_base, NULL, NULL, NULL);
|
||||||
|
#ifdef KEEP_XKB_LOCK_STATUS
|
||||||
if (wPreferences.modelock && !w_global.xext.xkb.supported) {
|
if (wPreferences.modelock && !w_global.xext.xkb.supported) {
|
||||||
wwarning(_("XKB is not supported. KbdModeLock is automatically disabled."));
|
wwarning(_("XKB is not supported. KbdModeLock is automatically disabled."));
|
||||||
wPreferences.modelock = 0;
|
wPreferences.modelock = 0;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
if (!w_global.xext.xkb.supported)
|
||||||
|
wwarning(_("XKB is not supported."));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (defaultScreenOnly)
|
if (defaultScreenOnly)
|
||||||
|
|||||||
@@ -48,6 +48,50 @@ static int initialized = 0;
|
|||||||
static void observer(void *self, WMNotification * notif);
|
static void observer(void *self, WMNotification * notif);
|
||||||
static void wsobserver(void *self, WMNotification * notif);
|
static void wsobserver(void *self, WMNotification * notif);
|
||||||
|
|
||||||
|
static WPixmap *switchMenuIconForWindow(WScreen *scr, WWindow *wwin)
|
||||||
|
{
|
||||||
|
RImage *image = NULL;
|
||||||
|
WPixmap *pix;
|
||||||
|
WApplication *wapp;
|
||||||
|
int max_size;
|
||||||
|
|
||||||
|
if (!scr || !wwin)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
max_size = WMFontHeight(scr->menu_entry_font) + 2;
|
||||||
|
if (max_size < 12)
|
||||||
|
max_size = 12;
|
||||||
|
|
||||||
|
/* Prefer the actual appicon image when available */
|
||||||
|
wapp = wApplicationOf(wwin->main_window);
|
||||||
|
if (wapp && wapp->app_icon && wapp->app_icon->icon && wapp->app_icon->icon->file_image) {
|
||||||
|
image = RRetainImage(wapp->app_icon->icon->file_image);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fall back to _NET_WM_ICON, then the default icon */
|
||||||
|
if (!image && !WFLAGP(wwin, always_user_icon) && wwin->net_icon_image)
|
||||||
|
image = RRetainImage(wwin->net_icon_image);
|
||||||
|
if (!image)
|
||||||
|
image = get_icon_image(scr, wwin->wm_instance, wwin->wm_class, max_size);
|
||||||
|
|
||||||
|
if (!image)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
image = wIconValidateIconSize(image, max_size);
|
||||||
|
if (!image)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
pix = wmalloc(sizeof(WPixmap));
|
||||||
|
memset(pix, 0, sizeof(WPixmap));
|
||||||
|
RConvertImageMask(scr->rcontext, image, &pix->image, &pix->mask, 128);
|
||||||
|
pix->width = image->width;
|
||||||
|
pix->height = image->height;
|
||||||
|
pix->depth = scr->w_depth;
|
||||||
|
|
||||||
|
RReleaseImage(image);
|
||||||
|
return pix;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* FocusWindow
|
* FocusWindow
|
||||||
*
|
*
|
||||||
@@ -216,6 +260,8 @@ void UpdateSwitchMenu(WScreen * scr, WWindow * wwin, int action)
|
|||||||
entry = wMenuInsertCallback(switchmenu, idx, t, focusWindow, wwin);
|
entry = wMenuInsertCallback(switchmenu, idx, t, focusWindow, wwin);
|
||||||
wfree(t);
|
wfree(t);
|
||||||
|
|
||||||
|
entry->icon = switchMenuIconForWindow(scr, wwin);
|
||||||
|
|
||||||
entry->flags.indicator = 1;
|
entry->flags.indicator = 1;
|
||||||
entry->rtext = wmalloc(MAX_WORKSPACENAME_WIDTH + 8);
|
entry->rtext = wmalloc(MAX_WORKSPACENAME_WIDTH + 8);
|
||||||
if (IS_OMNIPRESENT(wwin))
|
if (IS_OMNIPRESENT(wwin))
|
||||||
@@ -273,6 +319,7 @@ void UpdateSwitchMenu(WScreen * scr, WWindow * wwin, int action)
|
|||||||
if (entry->rtext) {
|
if (entry->rtext) {
|
||||||
int idx = -1;
|
int idx = -1;
|
||||||
char *t, *rt;
|
char *t, *rt;
|
||||||
|
WPixmap *ipix;
|
||||||
int it, ion;
|
int it, ion;
|
||||||
|
|
||||||
if (IS_OMNIPRESENT(wwin)) {
|
if (IS_OMNIPRESENT(wwin)) {
|
||||||
@@ -285,6 +332,8 @@ void UpdateSwitchMenu(WScreen * scr, WWindow * wwin, int action)
|
|||||||
|
|
||||||
rt = entry->rtext;
|
rt = entry->rtext;
|
||||||
entry->rtext = NULL;
|
entry->rtext = NULL;
|
||||||
|
ipix = entry->icon;
|
||||||
|
entry->icon = NULL;
|
||||||
t = entry->text;
|
t = entry->text;
|
||||||
entry->text = NULL;
|
entry->text = NULL;
|
||||||
|
|
||||||
@@ -300,6 +349,7 @@ void UpdateSwitchMenu(WScreen * scr, WWindow * wwin, int action)
|
|||||||
entry = wMenuInsertCallback(switchmenu, idx, t, focusWindow, wwin);
|
entry = wMenuInsertCallback(switchmenu, idx, t, focusWindow, wwin);
|
||||||
wfree(t);
|
wfree(t);
|
||||||
entry->rtext = rt;
|
entry->rtext = rt;
|
||||||
|
entry->icon = ipix;
|
||||||
entry->flags.indicator = 1;
|
entry->flags.indicator = 1;
|
||||||
entry->flags.indicator_type = it;
|
entry->flags.indicator_type = it;
|
||||||
entry->flags.indicator_on = ion;
|
entry->flags.indicator_on = ion;
|
||||||
|
|||||||
+9
-3
@@ -79,7 +79,7 @@ static short int label_height;
|
|||||||
|
|
||||||
static int canReceiveFocus(WWindow *wwin)
|
static int canReceiveFocus(WWindow *wwin)
|
||||||
{
|
{
|
||||||
if (wwin->frame->workspace != wwin->screen_ptr->current_workspace)
|
if (!wPreferences.cycle_all_workspaces && wwin->frame->workspace != wwin->screen_ptr->current_workspace)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (wPreferences.cycle_active_head_only &&
|
if (wPreferences.cycle_active_head_only &&
|
||||||
@@ -90,7 +90,7 @@ static int canReceiveFocus(WWindow *wwin)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (!wwin->flags.mapped) {
|
if (!wwin->flags.mapped) {
|
||||||
if (!wwin->flags.shaded && !wwin->flags.miniaturized && !wwin->flags.hidden)
|
if (!wwin->flags.shaded && !wwin->flags.miniaturized && !wwin->flags.hidden && !wPreferences.cycle_all_workspaces)
|
||||||
return 0;
|
return 0;
|
||||||
else
|
else
|
||||||
return -1;
|
return -1;
|
||||||
@@ -186,12 +186,18 @@ static void addIconForWindow(WSwitchPanel *panel, WMWidget *parent, WWindow *wwi
|
|||||||
{
|
{
|
||||||
WMFrame *icon = WMCreateFrame(parent);
|
WMFrame *icon = WMCreateFrame(parent);
|
||||||
RImage *image = NULL;
|
RImage *image = NULL;
|
||||||
|
WApplication *wapp;
|
||||||
|
|
||||||
WMSetFrameRelief(icon, WRFlat);
|
WMSetFrameRelief(icon, WRFlat);
|
||||||
WMResizeWidget(icon, icon_tile_size, icon_tile_size);
|
WMResizeWidget(icon, icon_tile_size, icon_tile_size);
|
||||||
WMMoveWidget(icon, x, y);
|
WMMoveWidget(icon, x, y);
|
||||||
|
|
||||||
if (!WFLAGP(wwin, always_user_icon) && wwin->net_icon_image)
|
wapp = wApplicationOf(wwin->main_window);
|
||||||
|
if (wapp && wapp->app_icon && wapp->app_icon->icon && wapp->app_icon->icon->file_image) {
|
||||||
|
image = RRetainImage(wapp->app_icon->icon->file_image);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!image && !WFLAGP(wwin, always_user_icon) && wwin->net_icon_image)
|
||||||
image = RRetainImage(wwin->net_icon_image);
|
image = RRetainImage(wwin->net_icon_image);
|
||||||
|
|
||||||
/* get_icon_image() includes the default icon image */
|
/* get_icon_image() includes the default icon image */
|
||||||
|
|||||||
+3
-36
@@ -43,14 +43,13 @@
|
|||||||
#include "icon.h"
|
#include "icon.h"
|
||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
|
|
||||||
#define APPLY_VAL(value, flag, attrib) \
|
#define APPLY_VAL(value, flag, attrib) \
|
||||||
if (value) {attr->flag = getBool(attrib, value); \
|
if (value) {attr->flag = WMPLGetBool(value); \
|
||||||
if (mask) mask->flag = 1;}
|
if (mask) mask->flag = 1;}
|
||||||
|
|
||||||
/* Local stuff */
|
/* Local stuff */
|
||||||
|
|
||||||
/* type converters */
|
/* type converters */
|
||||||
static int getBool(WMPropList *, WMPropList *);
|
|
||||||
static char *getString(WMPropList *, WMPropList *);
|
static char *getString(WMPropList *, WMPropList *);
|
||||||
static WMPropList *ANoTitlebar = NULL;
|
static WMPropList *ANoTitlebar = NULL;
|
||||||
static WMPropList *ANoResizebar;
|
static WMPropList *ANoResizebar;
|
||||||
@@ -634,38 +633,6 @@ void wDefaultPurgeInfo(const char *instance, const char *class)
|
|||||||
WMPLSetCaseSensitive(False);
|
WMPLSetCaseSensitive(False);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --------------------------- Local ----------------------- */
|
|
||||||
|
|
||||||
static int getBool(WMPropList * key, WMPropList * value)
|
|
||||||
{
|
|
||||||
char *val;
|
|
||||||
|
|
||||||
if (!WMIsPLString(value)) {
|
|
||||||
wwarning(_("Wrong option format for key \"%s\". Should be %s."),
|
|
||||||
WMGetFromPLString(key), "Boolean");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
val = WMGetFromPLString(value);
|
|
||||||
|
|
||||||
if ((val[1] == '\0' && (val[0] == 'y' || val[0] == 'Y' || val[0] == 'T' || val[0] == 't' || val[0] == '1'))
|
|
||||||
|| (strcasecmp(val, "YES") == 0 || strcasecmp(val, "TRUE") == 0)) {
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
} else if ((val[1] == '\0'
|
|
||||||
&& (val[0] == 'n' || val[0] == 'N' || val[0] == 'F' || val[0] == 'f' || val[0] == '0'))
|
|
||||||
|| (strcasecmp(val, "NO") == 0 || strcasecmp(val, "FALSE") == 0)) {
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
wwarning(_("can't convert \"%s\" to boolean"), val);
|
|
||||||
/* We return False if we can't convert to BOOLEAN.
|
|
||||||
* This is because all options defaults to False.
|
|
||||||
* -1 is not checked and thus is interpreted as True,
|
|
||||||
* which is not good.*/
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* WARNING: Do not free the value returned by this function!! */
|
/* WARNING: Do not free the value returned by this function!! */
|
||||||
static char *getString(WMPropList * key, WMPropList * value)
|
static char *getString(WMPropList * key, WMPropList * value)
|
||||||
{
|
{
|
||||||
|
|||||||
+15
-19
@@ -681,6 +681,15 @@ WWindow *wManageWindow(WScreen *scr, Window window)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Some applications create placeholder windows with 1x1 size
|
||||||
|
* (e.g. VirtualBox internal windows). Don't manage those initial
|
||||||
|
* 1x1 windows — wait for a proper ConfigureNotify/MapRequest with
|
||||||
|
* a real size. */
|
||||||
|
if (wattribs.width <= 1 && wattribs.height <= 1) {
|
||||||
|
XUngrabServer(dpy);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
wm_state = PropGetWindowState(window);
|
wm_state = PropGetWindowState(window);
|
||||||
|
|
||||||
/* if it's startup and the window is unmapped, don't manage it */
|
/* if it's startup and the window is unmapped, don't manage it */
|
||||||
@@ -1428,7 +1437,8 @@ WWindow *wManageInternalWindow(WScreen *scr, Window window, Window owner,
|
|||||||
foo = WFF_RIGHT_BUTTON | WFF_BORDER;
|
foo = WFF_RIGHT_BUTTON | WFF_BORDER;
|
||||||
foo |= WFF_TITLEBAR;
|
foo |= WFF_TITLEBAR;
|
||||||
#ifdef XKB_BUTTON_HINT
|
#ifdef XKB_BUTTON_HINT
|
||||||
foo |= WFF_LANGUAGE_BUTTON;
|
if (wPreferences.modelock)
|
||||||
|
foo |= WFF_LANGUAGE_BUTTON;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
wwin->frame = wFrameWindowCreate(scr, WMFloatingLevel,
|
wwin->frame = wFrameWindowCreate(scr, WMFloatingLevel,
|
||||||
@@ -2726,20 +2736,6 @@ WMagicNumber wWindowAddSavedState(const char *instance, const char *class,
|
|||||||
return wstate;
|
return wstate;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int is_same(const char *x, const char *y)
|
|
||||||
{
|
|
||||||
if ((x == NULL) && (y == NULL))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
if ((x == NULL) || (y == NULL))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (strcmp(x, y) == 0)
|
|
||||||
return 1;
|
|
||||||
else
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
WMagicNumber wWindowGetSavedState(Window win)
|
WMagicNumber wWindowGetSavedState(Window win)
|
||||||
{
|
{
|
||||||
char *instance, *class, *command = NULL;
|
char *instance, *class, *command = NULL;
|
||||||
@@ -2754,9 +2750,9 @@ WMagicNumber wWindowGetSavedState(Window win)
|
|||||||
|
|
||||||
if (PropGetWMClass(win, &class, &instance)) {
|
if (PropGetWMClass(win, &class, &instance)) {
|
||||||
while (wstate) {
|
while (wstate) {
|
||||||
if (is_same(instance, wstate->instance) &&
|
if (WMStrEqual(instance, wstate->instance) &&
|
||||||
is_same(class, wstate->class) &&
|
WMStrEqual(class, wstate->class) &&
|
||||||
is_same(command, wstate->command)) {
|
WMStrEqual(command, wstate->command)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
wstate = wstate->next;
|
wstate = wstate->next;
|
||||||
@@ -2982,7 +2978,7 @@ static void frameMouseDown(WObjDescriptor *desc, XEvent *event)
|
|||||||
|
|
||||||
CloseWindowMenu(wwin->screen_ptr);
|
CloseWindowMenu(wwin->screen_ptr);
|
||||||
|
|
||||||
if (!(event->xbutton.state & ControlMask) && !WFLAGP(wwin, no_focusable))
|
if (event->xbutton.button != Button4 && event->xbutton.button != Button5 && !(event->xbutton.state & ControlMask) && !WFLAGP(wwin, no_focusable))
|
||||||
wSetFocusTo(wwin->screen_ptr, wwin);
|
wSetFocusTo(wwin->screen_ptr, wwin);
|
||||||
|
|
||||||
if (event->xbutton.button == Button1)
|
if (event->xbutton.button == Button1)
|
||||||
|
|||||||
@@ -237,6 +237,12 @@ typedef struct WWindow {
|
|||||||
int cmap_window_no;
|
int cmap_window_no;
|
||||||
Window *cmap_windows;
|
Window *cmap_windows;
|
||||||
|
|
||||||
|
/* move/resize state for _NET_WM_MOVERESIZE support */
|
||||||
|
struct {
|
||||||
|
int active; /* 1 if move/resize is in progress */
|
||||||
|
int resize_edge; /* which edge for resize (0-7) */
|
||||||
|
} moveresize;
|
||||||
|
|
||||||
/* protocols */
|
/* protocols */
|
||||||
WProtocols protocols; /* accepted WM_PROTOCOLS */
|
WProtocols protocols; /* accepted WM_PROTOCOLS */
|
||||||
|
|
||||||
|
|||||||
+9
-28
@@ -55,7 +55,11 @@
|
|||||||
#define UPDATE_TEXT_FIELD 2
|
#define UPDATE_TEXT_FIELD 2
|
||||||
#define REVERT_TO_DEFAULT 4
|
#define REVERT_TO_DEFAULT 4
|
||||||
#define PWIDTH 290
|
#define PWIDTH 290
|
||||||
|
#ifdef XKB_BUTTON_HINT
|
||||||
|
#define PHEIGHT 380
|
||||||
|
#else
|
||||||
#define PHEIGHT 360
|
#define PHEIGHT 360
|
||||||
|
#endif
|
||||||
#define UNDEFINED_POS 0xffffff
|
#define UNDEFINED_POS 0xffffff
|
||||||
#define UPDATE_DEFAULTS 1
|
#define UPDATE_DEFAULTS 1
|
||||||
#define IS_BOOLEAN 2
|
#define IS_BOOLEAN 2
|
||||||
@@ -504,33 +508,6 @@ static int showIconFor(WMScreen *scrPtr, InspectorPanel *panel, const char *wm_i
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int getBool(WMPropList *value)
|
|
||||||
{
|
|
||||||
char *val;
|
|
||||||
|
|
||||||
if (!WMIsPLString(value))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
val = WMGetFromPLString(value);
|
|
||||||
if (val == NULL)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if ((val[1] == '\0' &&
|
|
||||||
(val[0] == 'y' || val[0] == 'Y' || val[0] == 'T' ||
|
|
||||||
val[0] == 't' || val[0] == '1')) ||
|
|
||||||
(strcasecmp(val, "YES") == 0 || strcasecmp(val, "TRUE") == 0)) {
|
|
||||||
return 1;
|
|
||||||
} else if ((val[1] == '\0' &&
|
|
||||||
(val[0] == 'n' || val[0] == 'N' || val[0] == 'F' ||
|
|
||||||
val[0] == 'f' || val[0] == '0')) ||
|
|
||||||
(strcasecmp(val, "NO") == 0 || strcasecmp(val, "FALSE") == 0)) {
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
wwarning(_("can't convert \"%s\" to boolean"), val);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Will insert the attribute = value; pair in window's list,
|
/* Will insert the attribute = value; pair in window's list,
|
||||||
* if it's different from the defaults.
|
* if it's different from the defaults.
|
||||||
* Defaults means either defaults database, or attributes saved
|
* Defaults means either defaults database, or attributes saved
|
||||||
@@ -554,7 +531,7 @@ insertAttribute(WMPropList *dict, WMPropList *window, WMPropList *attr, WMPropLi
|
|||||||
def_value = ((flags & IS_BOOLEAN) != 0) ? No : EmptyString;
|
def_value = ((flags & IS_BOOLEAN) != 0) ? No : EmptyString;
|
||||||
|
|
||||||
if (flags & IS_BOOLEAN)
|
if (flags & IS_BOOLEAN)
|
||||||
update = (getBool(value) != getBool(def_value));
|
update = (WMPLGetBool(value) != WMPLGetBool(def_value));
|
||||||
else
|
else
|
||||||
update = !WMIsPropListEqualTo(value, def_value);
|
update = !WMIsPropListEqualTo(value, def_value);
|
||||||
|
|
||||||
@@ -1342,7 +1319,11 @@ static void create_tab_window_advanced(WWindow *wwin, InspectorPanel *panel, int
|
|||||||
panel->moreFrm = WMCreateFrame(panel->win);
|
panel->moreFrm = WMCreateFrame(panel->win);
|
||||||
WMSetFrameTitle(panel->moreFrm, _("Advanced"));
|
WMSetFrameTitle(panel->moreFrm, _("Advanced"));
|
||||||
WMMoveWidget(panel->moreFrm, 15, 45);
|
WMMoveWidget(panel->moreFrm, 15, 45);
|
||||||
|
#ifdef XKB_BUTTON_HINT
|
||||||
|
WMResizeWidget(panel->moreFrm, frame_width, 285);
|
||||||
|
#else
|
||||||
WMResizeWidget(panel->moreFrm, frame_width, 265);
|
WMResizeWidget(panel->moreFrm, frame_width, 265);
|
||||||
|
#endif
|
||||||
|
|
||||||
for (i = 0; i < wlengthof(advanced_option); i++) {
|
for (i = 0; i < wlengthof(advanced_option); i++) {
|
||||||
int is_userdef, flag;
|
int is_userdef, flag;
|
||||||
|
|||||||
+104
-33
@@ -32,7 +32,9 @@
|
|||||||
|
|
||||||
#include <X11/Xlib.h>
|
#include <X11/Xlib.h>
|
||||||
#include <X11/Xatom.h>
|
#include <X11/Xatom.h>
|
||||||
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include <WINGs/WUtil.h>
|
#include <WINGs/WUtil.h>
|
||||||
#include "WindowMaker.h"
|
#include "WindowMaker.h"
|
||||||
@@ -69,7 +71,7 @@ static Atom net_showing_desktop;
|
|||||||
/* Other Root Window Messages */
|
/* Other Root Window Messages */
|
||||||
static Atom net_close_window;
|
static Atom net_close_window;
|
||||||
static Atom net_moveresize_window; /* TODO */
|
static Atom net_moveresize_window; /* TODO */
|
||||||
static Atom net_wm_moveresize; /* TODO */
|
static Atom net_wm_moveresize;
|
||||||
|
|
||||||
/* Application Window Properties */
|
/* Application Window Properties */
|
||||||
static Atom net_wm_name;
|
static Atom net_wm_name;
|
||||||
@@ -123,7 +125,7 @@ static Atom net_wm_strut;
|
|||||||
static Atom net_wm_strut_partial; /* TODO: doesn't really fit into the current strut scheme */
|
static Atom net_wm_strut_partial; /* TODO: doesn't really fit into the current strut scheme */
|
||||||
static Atom net_wm_icon_geometry; /* FIXME: should work together with net_wm_handled_icons, gnome-panel-2.2.0.1 doesn't use _NET_WM_HANDLED_ICONS, thus present situation. */
|
static Atom net_wm_icon_geometry; /* FIXME: should work together with net_wm_handled_icons, gnome-panel-2.2.0.1 doesn't use _NET_WM_HANDLED_ICONS, thus present situation. */
|
||||||
static Atom net_wm_icon;
|
static Atom net_wm_icon;
|
||||||
static Atom net_wm_pid; /* TODO */
|
static Atom net_wm_pid;
|
||||||
static Atom net_wm_handled_icons; /* FIXME: see net_wm_icon_geometry */
|
static Atom net_wm_handled_icons; /* FIXME: see net_wm_icon_geometry */
|
||||||
static Atom net_wm_window_opacity;
|
static Atom net_wm_window_opacity;
|
||||||
|
|
||||||
@@ -224,35 +226,6 @@ static atomitem_t atomNames[] = {
|
|||||||
#define _NET_WM_STATE_ADD 1
|
#define _NET_WM_STATE_ADD 1
|
||||||
#define _NET_WM_STATE_TOGGLE 2
|
#define _NET_WM_STATE_TOGGLE 2
|
||||||
|
|
||||||
#if 0
|
|
||||||
/*
|
|
||||||
* These constant provide information on the kind of window move/resize when
|
|
||||||
* it is initiated by the application instead of by WindowMaker. They are
|
|
||||||
* parameter for the client message _NET_WM_MOVERESIZE, as defined by the
|
|
||||||
* FreeDesktop wm-spec standard:
|
|
||||||
* http://standards.freedesktop.org/wm-spec/1.5/ar01s04.html
|
|
||||||
*
|
|
||||||
* Today, WindowMaker does not support this at all (the corresponding Atom
|
|
||||||
* is not added to the list in setSupportedHints), probably because there is
|
|
||||||
* nothing it needs to do about it, the application is assumed to know what
|
|
||||||
* it is doing, and WindowMaker won't get in the way.
|
|
||||||
*
|
|
||||||
* The definition of the constants (taken from the standard) are disabled to
|
|
||||||
* avoid a spurious warning (-Wunused-macros).
|
|
||||||
*/
|
|
||||||
#define _NET_WM_MOVERESIZE_SIZE_TOPLEFT 0
|
|
||||||
#define _NET_WM_MOVERESIZE_SIZE_TOP 1
|
|
||||||
#define _NET_WM_MOVERESIZE_SIZE_TOPRIGHT 2
|
|
||||||
#define _NET_WM_MOVERESIZE_SIZE_RIGHT 3
|
|
||||||
#define _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT 4
|
|
||||||
#define _NET_WM_MOVERESIZE_SIZE_BOTTOM 5
|
|
||||||
#define _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT 6
|
|
||||||
#define _NET_WM_MOVERESIZE_SIZE_LEFT 7
|
|
||||||
#define _NET_WM_MOVERESIZE_MOVE 8 /* movement only */
|
|
||||||
#define _NET_WM_MOVERESIZE_SIZE_KEYBOARD 9 /* size via keyboard */
|
|
||||||
#define _NET_WM_MOVERESIZE_MOVE_KEYBOARD 10 /* move via keyboard */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void observer(void *self, WMNotification *notif);
|
static void observer(void *self, WMNotification *notif);
|
||||||
static void wsobserver(void *self, WMNotification *notif);
|
static void wsobserver(void *self, WMNotification *notif);
|
||||||
|
|
||||||
@@ -274,6 +247,9 @@ static void setSupportedHints(WScreen *scr)
|
|||||||
{
|
{
|
||||||
Atom atom[wlengthof(atomNames)];
|
Atom atom[wlengthof(atomNames)];
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
long pid = 0;
|
||||||
|
char wm_name[64] = "";
|
||||||
|
XClassHint *class_hint;
|
||||||
|
|
||||||
/* set supported hints list */
|
/* set supported hints list */
|
||||||
/* XXX: extend this !!! */
|
/* XXX: extend this !!! */
|
||||||
@@ -289,9 +265,7 @@ static void setSupportedHints(WScreen *scr)
|
|||||||
atom[i++] = net_workarea;
|
atom[i++] = net_workarea;
|
||||||
atom[i++] = net_supporting_wm_check;
|
atom[i++] = net_supporting_wm_check;
|
||||||
atom[i++] = net_showing_desktop;
|
atom[i++] = net_showing_desktop;
|
||||||
#if 0
|
|
||||||
atom[i++] = net_wm_moveresize;
|
atom[i++] = net_wm_moveresize;
|
||||||
#endif
|
|
||||||
atom[i++] = net_wm_desktop;
|
atom[i++] = net_wm_desktop;
|
||||||
#ifdef USE_XINERAMA
|
#ifdef USE_XINERAMA
|
||||||
atom[i++] = net_wm_fullscreen_monitors;
|
atom[i++] = net_wm_fullscreen_monitors;
|
||||||
@@ -357,6 +331,25 @@ static void setSupportedHints(WScreen *scr)
|
|||||||
|
|
||||||
XChangeProperty(dpy, scr->info_window, net_supporting_wm_check, XA_WINDOW,
|
XChangeProperty(dpy, scr->info_window, net_supporting_wm_check, XA_WINDOW,
|
||||||
32, PropModeReplace, (unsigned char *)&scr->info_window, 1);
|
32, PropModeReplace, (unsigned char *)&scr->info_window, 1);
|
||||||
|
|
||||||
|
/* set _NET_WM_NAME on supporting window */
|
||||||
|
snprintf(wm_name, sizeof(wm_name), "WindowMaker %s", VERSION);
|
||||||
|
XChangeProperty(dpy, scr->info_window, net_wm_name, utf8_string, 8,
|
||||||
|
PropModeReplace, (unsigned char *)wm_name, strlen(wm_name));
|
||||||
|
|
||||||
|
/* set _NET_WM_PID on supporting window */
|
||||||
|
pid = getpid();
|
||||||
|
XChangeProperty(dpy, scr->info_window, net_wm_pid, XA_CARDINAL, 32,
|
||||||
|
PropModeReplace, (unsigned char *)&pid, 1);
|
||||||
|
|
||||||
|
/* set WM_CLASS on supporting window */
|
||||||
|
class_hint = XAllocClassHint();
|
||||||
|
if (class_hint) {
|
||||||
|
class_hint->res_name = "wmaker";
|
||||||
|
class_hint->res_class = "WindowMaker";
|
||||||
|
XSetClassHint(dpy, scr->info_window, class_hint);
|
||||||
|
XFree(class_hint);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void wNETWMUpdateDesktop(WScreen *scr)
|
void wNETWMUpdateDesktop(WScreen *scr)
|
||||||
@@ -1790,6 +1783,84 @@ Bool wNETWMProcessClientMessage(XClientMessageEvent *event)
|
|||||||
}
|
}
|
||||||
return True;
|
return True;
|
||||||
|
|
||||||
|
} else if (event->message_type == net_wm_moveresize) {
|
||||||
|
XEvent fake_event;
|
||||||
|
int direction = event->data.l[2];
|
||||||
|
int x_root = event->data.l[0];
|
||||||
|
int y_root = event->data.l[1];
|
||||||
|
int button = event->data.l[3];
|
||||||
|
int junk;
|
||||||
|
Window junkw;
|
||||||
|
unsigned int mask;
|
||||||
|
|
||||||
|
if (direction == _NET_WM_MOVERESIZE_CANCEL) {
|
||||||
|
if (wwin->moveresize.active) {
|
||||||
|
memset(&fake_event, 0, sizeof(XEvent));
|
||||||
|
fake_event.type = ButtonRelease;
|
||||||
|
fake_event.xbutton.window = wwin->frame->core->window;
|
||||||
|
fake_event.xbutton.x_root = x_root;
|
||||||
|
fake_event.xbutton.y_root = y_root;
|
||||||
|
fake_event.xbutton.button = event->data.l[3];
|
||||||
|
XSendEvent(dpy, wwin->frame->core->window, False, ButtonReleaseMask, &fake_event);
|
||||||
|
}
|
||||||
|
return True;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if already in progress */
|
||||||
|
if (wwin->moveresize.active)
|
||||||
|
return True;
|
||||||
|
|
||||||
|
/* Check if the initiating button is actually pressed */
|
||||||
|
if (!XQueryPointer(dpy, wwin->screen_ptr->root_win, &junkw, &junkw,
|
||||||
|
&junk, &junk, &junk, &junk, &mask))
|
||||||
|
return True;
|
||||||
|
|
||||||
|
if (button > 0) {
|
||||||
|
unsigned int expected =
|
||||||
|
button == 1 ? Button1Mask :
|
||||||
|
button == 2 ? Button2Mask :
|
||||||
|
button == 3 ? Button3Mask :
|
||||||
|
0;
|
||||||
|
|
||||||
|
if (expected && !(mask & expected))
|
||||||
|
/* Race: button already released */
|
||||||
|
return True;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if operation is allowed */
|
||||||
|
if (direction == _NET_WM_MOVERESIZE_MOVE) {
|
||||||
|
if (WFLAGP(wwin, no_movable))
|
||||||
|
return True;
|
||||||
|
} else if (direction <= _NET_WM_MOVERESIZE_SIZE_LEFT) {
|
||||||
|
if (WFLAGP(wwin, no_resizable))
|
||||||
|
return True;
|
||||||
|
} else {
|
||||||
|
return True;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Grab the pointer for the operation */
|
||||||
|
if (XGrabPointer(dpy, wwin->frame->core->window, False,
|
||||||
|
ButtonReleaseMask | PointerMotionMask | ButtonPressMask,
|
||||||
|
GrabModeAsync, GrabModeAsync,
|
||||||
|
None, None, CurrentTime) != GrabSuccess)
|
||||||
|
return True;
|
||||||
|
|
||||||
|
/* Set up the move/resize state */
|
||||||
|
wwin->moveresize.active = 1;
|
||||||
|
wwin->moveresize.resize_edge = direction;
|
||||||
|
|
||||||
|
memset(&fake_event, 0, sizeof(XEvent));
|
||||||
|
fake_event.type = MotionNotify;
|
||||||
|
fake_event.xmotion.x_root = x_root;
|
||||||
|
fake_event.xmotion.y_root = y_root;
|
||||||
|
fake_event.xmotion.window = wwin->frame->core->window;
|
||||||
|
if (direction == _NET_WM_MOVERESIZE_MOVE)
|
||||||
|
wMouseMoveWindow(wwin, &fake_event);
|
||||||
|
else
|
||||||
|
wMouseResizeWindow(wwin, &fake_event);
|
||||||
|
|
||||||
|
return True;
|
||||||
|
|
||||||
#ifdef USE_XINERAMA
|
#ifdef USE_XINERAMA
|
||||||
} else if (event->message_type == net_wm_fullscreen_monitors) {
|
} else if (event->message_type == net_wm_fullscreen_monitors) {
|
||||||
unsigned long top, bottom, left, right, src_indication;
|
unsigned long top, bottom, left, right, src_indication;
|
||||||
|
|||||||
@@ -28,6 +28,26 @@
|
|||||||
#include "window.h"
|
#include "window.h"
|
||||||
#include <X11/Xlib.h>
|
#include <X11/Xlib.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* These constant provide information on the kind of window move/resize when
|
||||||
|
* it is initiated by the application instead of by WindowMaker. They are
|
||||||
|
* parameter for the client message _NET_WM_MOVERESIZE, as defined by the
|
||||||
|
* FreeDesktop wm-spec standard:
|
||||||
|
* http://standards.freedesktop.org/wm-spec/1.5/ar01s04.html
|
||||||
|
*/
|
||||||
|
#define _NET_WM_MOVERESIZE_SIZE_TOPLEFT 0
|
||||||
|
#define _NET_WM_MOVERESIZE_SIZE_TOP 1
|
||||||
|
#define _NET_WM_MOVERESIZE_SIZE_TOPRIGHT 2
|
||||||
|
#define _NET_WM_MOVERESIZE_SIZE_RIGHT 3
|
||||||
|
#define _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT 4
|
||||||
|
#define _NET_WM_MOVERESIZE_SIZE_BOTTOM 5
|
||||||
|
#define _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT 6
|
||||||
|
#define _NET_WM_MOVERESIZE_SIZE_LEFT 7
|
||||||
|
#define _NET_WM_MOVERESIZE_MOVE 8 /* movement only */
|
||||||
|
#define _NET_WM_MOVERESIZE_SIZE_KEYBOARD 9 /* size via keyboard */
|
||||||
|
#define _NET_WM_MOVERESIZE_MOVE_KEYBOARD 10 /* move via keyboard */
|
||||||
|
#define _NET_WM_MOVERESIZE_CANCEL 11 /* cancel operation */
|
||||||
|
|
||||||
void wNETWMInitStuff(WScreen *scr);
|
void wNETWMInitStuff(WScreen *scr);
|
||||||
void wNETWMCleanup(WScreen *scr);
|
void wNETWMCleanup(WScreen *scr);
|
||||||
void wNETWMUpdateWorkarea(WScreen *scr);
|
void wNETWMUpdateWorkarea(WScreen *scr);
|
||||||
|
|||||||
+3
-2
@@ -76,9 +76,10 @@ wmiv_LDADD = \
|
|||||||
$(top_builddir)/wrlib/libwraster.la \
|
$(top_builddir)/wrlib/libwraster.la \
|
||||||
$(top_builddir)/WINGs/libWINGs.la \
|
$(top_builddir)/WINGs/libWINGs.la \
|
||||||
@XLFLAGS@ @XLIBS@ @GFXLIBS@ \
|
@XLFLAGS@ @XLIBS@ @GFXLIBS@ \
|
||||||
@PANGO_LIBS@ @PTHREAD_LIBS@ @LIBEXIF@
|
@PANGO_LIBS@ @PTHREAD_LIBS@ @LIBEXIF@ \
|
||||||
|
@LIBARCHIVE_LIBS@ @LIBM@ @LIBXRANDR@
|
||||||
|
|
||||||
wmiv_SOURCES = wmiv.c wmiv.h
|
wmiv_SOURCES = wmiv.c wmiv.hi xdnd.c xdnd.h
|
||||||
|
|
||||||
CLEANFILES = wmaker.inst
|
CLEANFILES = wmaker.inst
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -2,7 +2,7 @@ File Language Note Current Maintainer
|
|||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
nl.po Dutch Alwin <translations@ziggo.nl>
|
nl.po Dutch Alwin <translations@ziggo.nl>
|
||||||
fy.po Frisian Alwin <translations@ziggo.nl>
|
fy.po Frisian Alwin <translations@ziggo.nl>
|
||||||
sr.po Serbian Strahinya Radich <contact@strahinja.org>
|
sr.po Serbian Strahinya Radich <sr@strahinja.org>
|
||||||
|
|
||||||
Notes
|
Notes
|
||||||
-----
|
-----
|
||||||
|
|||||||
+2
-2
@@ -3,7 +3,7 @@
|
|||||||
# 1998-2006 Dan Pascu
|
# 1998-2006 Dan Pascu
|
||||||
# 2013-2020 Window Maker Developers Team
|
# 2013-2020 Window Maker Developers Team
|
||||||
# This file is distributed under the same license as the Window Maker package.
|
# This file is distributed under the same license as the Window Maker package.
|
||||||
# Strahinya Radich (Страхиња Радић) <contact@strahinja.org>, 2023.
|
# Strahinya Radich (Страхиња Радић) <sr@strahinja.org>, 2023.
|
||||||
#
|
#
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -11,7 +11,7 @@ msgstr ""
|
|||||||
"Report-Msgid-Bugs-To: wmaker-dev@googlegroups.com\n"
|
"Report-Msgid-Bugs-To: wmaker-dev@googlegroups.com\n"
|
||||||
"POT-Creation-Date: 2023-11-02 19:43+0100\n"
|
"POT-Creation-Date: 2023-11-02 19:43+0100\n"
|
||||||
"PO-Revision-Date: 2023-11-02 19:48+0100\n"
|
"PO-Revision-Date: 2023-11-02 19:48+0100\n"
|
||||||
"Last-Translator: Страхиња Радић <contact@strahinja.org>\n"
|
"Last-Translator: Страхиња Радић <sr@strahinja.org>\n"
|
||||||
"Language-Team: Serbian <sr@li.org>\n"
|
"Language-Team: Serbian <sr@li.org>\n"
|
||||||
"Language: sr\n"
|
"Language: sr\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
|
|||||||
+1494
-229
File diff suppressed because it is too large
Load Diff
+1596
File diff suppressed because it is too large
Load Diff
+219
@@ -0,0 +1,219 @@
|
|||||||
|
/* xdnd.c, xdnd.h - C program library for handling the Xdnd protocol
|
||||||
|
Copyright (C) 1996-2000 Paul Sheer
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||||
|
02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _X_DND_H
|
||||||
|
#define _X_DND_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* you can set this to either 2 (which support 0 and 1 as well) or 3 */
|
||||||
|
/* #define XDND_VERSION 2 */
|
||||||
|
|
||||||
|
#define XDND_VERSION 3
|
||||||
|
|
||||||
|
/* XdndEnter */
|
||||||
|
#define XDND_THREE 3
|
||||||
|
#define XDND_ENTER_SOURCE_WIN(e) ((e)->xclient.data.l[0])
|
||||||
|
#define XDND_ENTER_THREE_TYPES(e) (((e)->xclient.data.l[1] & 0x1UL) == 0)
|
||||||
|
#define XDND_ENTER_THREE_TYPES_SET(e,b) (e)->xclient.data.l[1] = ((e)->xclient.data.l[1] & ~0x1UL) | (((b) == 0) ? 0 : 0x1UL)
|
||||||
|
#define XDND_ENTER_VERSION(e) ((e)->xclient.data.l[1] >> 24)
|
||||||
|
#define XDND_ENTER_VERSION_SET(e,v) (e)->xclient.data.l[1] = ((e)->xclient.data.l[1] & ~(0xFF << 24)) | ((v) << 24)
|
||||||
|
#define XDND_ENTER_TYPE(e,i) ((e)->xclient.data.l[2 + i]) /* i => (0, 1, 2) */
|
||||||
|
|
||||||
|
/* XdndPosition */
|
||||||
|
#define XDND_POSITION_SOURCE_WIN(e) ((e)->xclient.data.l[0])
|
||||||
|
#define XDND_POSITION_ROOT_X(e) ((e)->xclient.data.l[2] >> 16)
|
||||||
|
#define XDND_POSITION_ROOT_Y(e) ((e)->xclient.data.l[2] & 0xFFFFUL)
|
||||||
|
#define XDND_POSITION_ROOT_SET(e,x,y) (e)->xclient.data.l[2] = ((x) << 16) | ((y) & 0xFFFFUL)
|
||||||
|
#define XDND_POSITION_TIME(e) ((e)->xclient.data.l[3])
|
||||||
|
#define XDND_POSITION_ACTION(e) ((e)->xclient.data.l[4])
|
||||||
|
|
||||||
|
/* XdndStatus */
|
||||||
|
#define XDND_STATUS_TARGET_WIN(e) ((e)->xclient.data.l[0])
|
||||||
|
#define XDND_STATUS_WILL_ACCEPT(e) ((e)->xclient.data.l[1] & 0x1L)
|
||||||
|
#define XDND_STATUS_WILL_ACCEPT_SET(e,b) (e)->xclient.data.l[1] = ((e)->xclient.data.l[1] & ~0x1UL) | (((b) == 0) ? 0 : 0x1UL)
|
||||||
|
#define XDND_STATUS_WANT_POSITION(e) ((e)->xclient.data.l[1] & 0x2UL)
|
||||||
|
#define XDND_STATUS_WANT_POSITION_SET(e,b) (e)->xclient.data.l[1] = ((e)->xclient.data.l[1] & ~0x2UL) | (((b) == 0) ? 0 : 0x2UL)
|
||||||
|
#define XDND_STATUS_RECT_X(e) ((e)->xclient.data.l[2] >> 16)
|
||||||
|
#define XDND_STATUS_RECT_Y(e) ((e)->xclient.data.l[2] & 0xFFFFL)
|
||||||
|
#define XDND_STATUS_RECT_WIDTH(e) ((e)->xclient.data.l[3] >> 16)
|
||||||
|
#define XDND_STATUS_RECT_HEIGHT(e) ((e)->xclient.data.l[3] & 0xFFFFL)
|
||||||
|
#define XDND_STATUS_RECT_SET(e,x,y,w,h) {(e)->xclient.data.l[2] = ((x) << 16) | ((y) & 0xFFFFUL); (e)->xclient.data.l[3] = ((w) << 16) | ((h) & 0xFFFFUL); }
|
||||||
|
#define XDND_STATUS_ACTION(e) ((e)->xclient.data.l[4])
|
||||||
|
|
||||||
|
/* XdndLeave */
|
||||||
|
#define XDND_LEAVE_SOURCE_WIN(e) ((e)->xclient.data.l[0])
|
||||||
|
|
||||||
|
/* XdndDrop */
|
||||||
|
#define XDND_DROP_SOURCE_WIN(e) ((e)->xclient.data.l[0])
|
||||||
|
#define XDND_DROP_TIME(e) ((e)->xclient.data.l[2])
|
||||||
|
|
||||||
|
/* XdndFinished */
|
||||||
|
#define XDND_FINISHED_TARGET_WIN(e) ((e)->xclient.data.l[0])
|
||||||
|
|
||||||
|
struct _DndCursor {
|
||||||
|
int width, height;
|
||||||
|
int x, y;
|
||||||
|
unsigned char *image_data, *mask_data;
|
||||||
|
char *_action;
|
||||||
|
Pixmap image_pixmap, mask_pixmap;
|
||||||
|
Cursor cursor;
|
||||||
|
Atom action;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct _DndCursor DndCursor;
|
||||||
|
typedef struct _DndClass DndClass;
|
||||||
|
|
||||||
|
struct _DndClass {
|
||||||
|
/* insert chars sequentionally into the target widget, type will be the same as `desired_type'
|
||||||
|
returned from widget_apply_position. This may be called several times in succession
|
||||||
|
with sequention blocks of data. Must return non-zero on failure */
|
||||||
|
int (*widget_insert_drop) (DndClass * dnd, unsigned char *data, int length, int remaining, Window into, Window from, Atom type);
|
||||||
|
|
||||||
|
/* In response to DELETE requests : FIXME - not yet used */
|
||||||
|
int (*widget_delete_selection) (DndClass * dnd, Window window, Window from);
|
||||||
|
|
||||||
|
/* returns 1 if widget exists, zero otherwise. If this method is not
|
||||||
|
set then the code assumes that no widgets have support for recieving drops.
|
||||||
|
In this case none of the widget methods need be set. */
|
||||||
|
int (*widget_exists) (DndClass * dnd, Window window);
|
||||||
|
|
||||||
|
/* must update the widgets border to its default appearance */
|
||||||
|
void (*widget_apply_leave) (DndClass * dnd, Window widgets_window);
|
||||||
|
|
||||||
|
/* must update the widgets border to give the appearance of being able to recieve a drop,
|
||||||
|
plus return all data to pointers. As per the protocol, if the widget cannot
|
||||||
|
perform the action specified by `action' then it should return either XdndActionPrivate
|
||||||
|
or XdndActionCopy into supported_action (leaving 0 supported_action unchanged is equivalent
|
||||||
|
to XdndActionCopy). Returns 1 if ready to ok drop */
|
||||||
|
int (*widget_apply_position) (DndClass * dnd, Window widgets_window, Window from,
|
||||||
|
Atom action, int x, int y, Time t, Atom * typelist,
|
||||||
|
int *want_position, Atom * supported_action, Atom * desired_type,
|
||||||
|
XRectangle * rectangle);
|
||||||
|
|
||||||
|
/* returns drag data of the specified type. This will be one of `typelist' given to xdnd_drag */
|
||||||
|
void (*widget_get_data) (DndClass * dnd, Window window, unsigned char **data, int *length, Atom type);
|
||||||
|
|
||||||
|
/* this is called from with the main event loop if an expose event is recieved and is optional */
|
||||||
|
void (*handle_expose_events) (DndClass * dnd, XEvent * xevent);
|
||||||
|
|
||||||
|
/* creates a chooser dialog if the action is XdndActionAsk. Returns non-zero on cancel */
|
||||||
|
int (*action_choose_dialog) (DndClass * dnd, char **descriptions, Atom * actions, Atom * result);
|
||||||
|
|
||||||
|
#if 0 /* implemented internally */
|
||||||
|
/* returns a widget that is dnd aware within a parent widget that lies under the point x, y */
|
||||||
|
Window (*widget_get_child_widget) (DndClass * dnd, Window parent, int x, int y);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void *pad1[8];
|
||||||
|
|
||||||
|
DndCursor *cursors;
|
||||||
|
|
||||||
|
Display *display;
|
||||||
|
|
||||||
|
Atom XdndAware;
|
||||||
|
Atom XdndSelection;
|
||||||
|
Atom XdndEnter;
|
||||||
|
Atom XdndLeave;
|
||||||
|
Atom XdndPosition;
|
||||||
|
Atom XdndDrop;
|
||||||
|
Atom XdndFinished;
|
||||||
|
Atom XdndStatus;
|
||||||
|
Atom XdndActionCopy;
|
||||||
|
Atom XdndActionMove;
|
||||||
|
Atom XdndActionLink;
|
||||||
|
Atom XdndActionAsk;
|
||||||
|
Atom XdndActionPrivate;
|
||||||
|
Atom XdndTypeList;
|
||||||
|
Atom XdndActionList;
|
||||||
|
Atom XdndActionDescription;
|
||||||
|
|
||||||
|
Atom Xdnd_NON_PROTOCOL_ATOM;
|
||||||
|
Atom version;
|
||||||
|
|
||||||
|
Atom pad2[16];
|
||||||
|
|
||||||
|
Window root_window;
|
||||||
|
|
||||||
|
#define XDND_DROP_STAGE_IDLE 0
|
||||||
|
#define XDND_DRAG_STAGE_DRAGGING 1
|
||||||
|
#define XDND_DRAG_STAGE_ENTERED 2
|
||||||
|
#define XDND_DROP_STAGE_CONVERTING 3
|
||||||
|
#define XDND_DROP_STAGE_ENTERED 4
|
||||||
|
int stage;
|
||||||
|
int dragging_version;
|
||||||
|
int internal_drag;
|
||||||
|
int want_position;
|
||||||
|
int ready_to_drop;
|
||||||
|
int will_accept;
|
||||||
|
XRectangle rectangle;
|
||||||
|
Window dropper_window, dragger_window;
|
||||||
|
Atom *dragger_typelist;
|
||||||
|
Atom desired_type;
|
||||||
|
Atom supported_action;
|
||||||
|
Time time;
|
||||||
|
/* drop position from last XdndPosition */
|
||||||
|
int x, y;
|
||||||
|
int pad3[16];
|
||||||
|
|
||||||
|
/* move euclidian pixels before considering this to be an actual drag */
|
||||||
|
float drag_threshold;
|
||||||
|
|
||||||
|
/* block for only this many seconds on not receiving a XdndFinished from target, default : 10 */
|
||||||
|
int time_out;
|
||||||
|
|
||||||
|
#define XDND_OPTION_NO_HYSTERESIS (1<<0)
|
||||||
|
int options;
|
||||||
|
|
||||||
|
/* user hooks */
|
||||||
|
void *user_hook1;
|
||||||
|
void *user_hook2;
|
||||||
|
void *user_hook3;
|
||||||
|
Window dropper_toplevel;
|
||||||
|
void *pad4[15];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void xdnd_init (DndClass * dnd, Display * display);
|
||||||
|
void xdnd_shut (DndClass * dnd);
|
||||||
|
/* for nested widgets where parent and child receive drops of different
|
||||||
|
types; then always pass typelist as null */
|
||||||
|
void xdnd_set_dnd_aware (DndClass * dnd, Window window, Atom * typelist);
|
||||||
|
int xdnd_is_dnd_aware (DndClass * dnd, Window window, int *version, Atom * typelist);
|
||||||
|
void xdnd_set_type_list (DndClass * dnd, Window window, Atom * typelist);
|
||||||
|
void xdnd_set_actions (DndClass * dnd, Window window, Atom * actions, char **descriptions);
|
||||||
|
int xdnd_get_actions (DndClass * dnd, Window window, Atom ** actions, char ***descriptions);
|
||||||
|
int xdnd_choose_action_dialog (DndClass * dnd, Atom * actions, char **descriptions, Atom * result);
|
||||||
|
Atom xdnd_drag (DndClass * dnd, Window from, Atom action, Atom * typelist);
|
||||||
|
|
||||||
|
/* Returns 1 if event is handled, This must be placed in the widget
|
||||||
|
libraries main event loop and be called if the event type is
|
||||||
|
ClientMessage or SelectionNotify */
|
||||||
|
int xdnd_handle_drop_events (DndClass * dnd, XEvent * xevent);
|
||||||
|
Atom xdnd_get_drop (Display * display, XEvent * xevent, Atom * typelist, Atom * actionlist,
|
||||||
|
unsigned char **data, int *length, Atom * type, int *x, int *y);
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* !_X_DND_H */
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
- added RSaveRawImage()
|
||||||
|
|
||||||
- added RSaveTitledImage()
|
- added RSaveTitledImage()
|
||||||
|
|
||||||
- removed obsoleted RDestroyImage()
|
- removed obsoleted RDestroyImage()
|
||||||
|
|||||||
@@ -58,6 +58,10 @@ libwraster_la_SOURCES += load_jpeg.c
|
|||||||
libwraster_la_SOURCES += save_jpeg.c
|
libwraster_la_SOURCES += save_jpeg.c
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
if USE_JXL
|
||||||
|
libwraster_la_SOURCES += load_jxl.c
|
||||||
|
endif
|
||||||
|
|
||||||
if USE_PNG
|
if USE_PNG
|
||||||
libwraster_la_SOURCES += load_png.c
|
libwraster_la_SOURCES += load_png.c
|
||||||
libwraster_la_SOURCES += save_png.c
|
libwraster_la_SOURCES += save_png.c
|
||||||
|
|||||||
+38
-38
@@ -25,47 +25,47 @@
|
|||||||
|
|
||||||
|
|
||||||
void RCombineAlpha(unsigned char *d, unsigned char *s, int s_has_alpha,
|
void RCombineAlpha(unsigned char *d, unsigned char *s, int s_has_alpha,
|
||||||
int width, int height, int dwi, int swi, int opacity) {
|
int width, int height, int dwi, int swi, int opacity) {
|
||||||
int x, y;
|
int x, y;
|
||||||
int t, sa;
|
unsigned char *dst = d;
|
||||||
int alpha;
|
unsigned char *src = s;
|
||||||
float ratio, cratio;
|
|
||||||
|
|
||||||
for (y=0; y<height; y++) {
|
for (y = 0; y < height; y++) {
|
||||||
for (x=0; x<width; x++) {
|
for (x = 0; x < width; x++) {
|
||||||
sa=s_has_alpha?*(s+3):255;
|
int sa = s_has_alpha ? src[3] : 255;
|
||||||
|
int t, alpha;
|
||||||
|
|
||||||
if (opacity!=255) {
|
if (opacity != 255) {
|
||||||
t = sa * opacity + 0x80;
|
t = sa * opacity + 0x80;
|
||||||
sa = ((t>>8)+t)>>8;
|
sa = ((t >> 8) + t) >> 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
t = *(d+3) * (255-sa) + 0x80;
|
t = dst[3] * (255 - sa) + 0x80;
|
||||||
alpha = sa + (((t>>8)+t)>>8);
|
alpha = sa + (((t >> 8) + t) >> 8);
|
||||||
|
|
||||||
if (sa==0 || alpha==0) {
|
if (alpha == 0) {
|
||||||
ratio = 0;
|
dst[3] = 0;
|
||||||
cratio = 1.0;
|
} else if (sa == alpha) {
|
||||||
} else if(sa == alpha) {
|
dst[0] = src[0];
|
||||||
ratio = 1.0;
|
dst[1] = src[1];
|
||||||
cratio = 0;
|
dst[2] = src[2];
|
||||||
} else {
|
dst[3] = alpha;
|
||||||
ratio = (float)sa / alpha;
|
} else if (sa == 0) {
|
||||||
cratio = 1.0F - ratio;
|
dst[3] = alpha;
|
||||||
}
|
} else {
|
||||||
|
int ratio = (sa << 8) / alpha;
|
||||||
|
int inv_ratio = 256 - ratio;
|
||||||
|
|
||||||
*d = (int)*d * cratio + (int)*s * ratio;
|
dst[0] = (dst[0] * inv_ratio + src[0] * ratio) >> 8;
|
||||||
s++; d++;
|
dst[1] = (dst[1] * inv_ratio + src[1] * ratio) >> 8;
|
||||||
*d = (int)*d * cratio + (int)*s * ratio;
|
dst[2] = (dst[2] * inv_ratio + src[2] * ratio) >> 8;
|
||||||
s++; d++;
|
dst[3] = alpha;
|
||||||
*d = (int)*d * cratio + (int)*s * ratio;
|
}
|
||||||
s++; d++;
|
|
||||||
*d = alpha;
|
|
||||||
d++;
|
|
||||||
|
|
||||||
if (s_has_alpha) s++;
|
dst += 4;
|
||||||
}
|
src += s_has_alpha ? 4 : 3;
|
||||||
d+=dwi;
|
}
|
||||||
s+=swi;
|
dst += dwi;
|
||||||
}
|
src += swi;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
+1
-1
@@ -554,7 +554,7 @@ RContext *RCreateContext(Display * dpy, int screen_number, const RContextAttribu
|
|||||||
|
|
||||||
if (!(context->attribs->flags & RC_ScalingFilter)) {
|
if (!(context->attribs->flags & RC_ScalingFilter)) {
|
||||||
context->attribs->flags |= RC_ScalingFilter;
|
context->attribs->flags |= RC_ScalingFilter;
|
||||||
context->attribs->scaling_filter = RMitchellFilter;
|
context->attribs->scaling_filter = RCatmullRomFilter;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get configuration from environment variables */
|
/* get configuration from environment variables */
|
||||||
|
|||||||
+9
-2
@@ -38,12 +38,13 @@ typedef enum {
|
|||||||
IM_PPM = 4,
|
IM_PPM = 4,
|
||||||
IM_JPEG = 5,
|
IM_JPEG = 5,
|
||||||
IM_GIF = 6,
|
IM_GIF = 6,
|
||||||
IM_WEBP = 7
|
IM_WEBP = 7,
|
||||||
|
IM_JXL = 8
|
||||||
} WRImgFormat;
|
} WRImgFormat;
|
||||||
|
|
||||||
/* How many image types we have. */
|
/* How many image types we have. */
|
||||||
/* Increase this when adding new image types! */
|
/* Increase this when adding new image types! */
|
||||||
#define IM_TYPES 7
|
#define IM_TYPES 8
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Function for Loading in a specific format
|
* Function for Loading in a specific format
|
||||||
@@ -64,6 +65,10 @@ RImage *RLoadPNG(RContext *context, const char *file);
|
|||||||
RImage *RLoadJPEG(const char *file);
|
RImage *RLoadJPEG(const char *file);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_JXL
|
||||||
|
RImage *RLoadJXL(const char *file);
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef USE_GIF
|
#ifdef USE_GIF
|
||||||
RImage *RLoadGIF(const char *file, int index);
|
RImage *RLoadGIF(const char *file, int index);
|
||||||
#endif
|
#endif
|
||||||
@@ -85,10 +90,12 @@ Bool RSaveXPM(RImage *image, const char *filename);
|
|||||||
|
|
||||||
#ifdef USE_PNG
|
#ifdef USE_PNG
|
||||||
Bool RSavePNG(RImage *image, const char *filename, char *title);
|
Bool RSavePNG(RImage *image, const char *filename, char *title);
|
||||||
|
Bool RSaveRawPNG(RImage *image, char *title, unsigned char **out_buf, size_t *out_size);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef USE_JPEG
|
#ifdef USE_JPEG
|
||||||
Bool RSaveJPEG(RImage *image, const char *filename, char *title);
|
Bool RSaveJPEG(RImage *image, const char *filename, char *title);
|
||||||
|
Bool RSaveRawJPEG(RImage *image, char *title, unsigned char **out_buf, size_t *out_size);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
+27
-1
@@ -3,7 +3,7 @@
|
|||||||
* Raster graphics library
|
* Raster graphics library
|
||||||
*
|
*
|
||||||
* Copyright (c) 1997-2003 Alfredo K. Kojima
|
* Copyright (c) 1997-2003 Alfredo K. Kojima
|
||||||
* Copyright (c) 2014-2021 Window Maker Team
|
* Copyright (c) 2014-2025 Window Maker Team
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Library General Public
|
* modify it under the terms of the GNU Library General Public
|
||||||
@@ -93,6 +93,9 @@ char **RSupportedFileFormats(void)
|
|||||||
#ifdef USE_JPEG
|
#ifdef USE_JPEG
|
||||||
tmp[i++] = "JPEG";
|
tmp[i++] = "JPEG";
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef USE_JXL
|
||||||
|
tmp[i++] = "JXL";
|
||||||
|
#endif
|
||||||
#ifdef USE_GIF
|
#ifdef USE_GIF
|
||||||
tmp[i++] = "GIF";
|
tmp[i++] = "GIF";
|
||||||
#endif
|
#endif
|
||||||
@@ -159,6 +162,11 @@ RImage *RLoadImage(RContext *context, const char *file, int index)
|
|||||||
|
|
||||||
assert(file != NULL);
|
assert(file != NULL);
|
||||||
|
|
||||||
|
/* just to suppress the compilation warning as index is only used with TIFF and GIF */
|
||||||
|
#if !defined(USE_TIFF) && !defined(USE_GIF)
|
||||||
|
(void)index;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (RImageCacheSize < 0)
|
if (RImageCacheSize < 0)
|
||||||
init_cache();
|
init_cache();
|
||||||
|
|
||||||
@@ -219,6 +227,12 @@ RImage *RLoadImage(RContext *context, const char *file, int index)
|
|||||||
break;
|
break;
|
||||||
#endif /* USE_JPEG */
|
#endif /* USE_JPEG */
|
||||||
|
|
||||||
|
#ifdef USE_JXL
|
||||||
|
case IM_JXL:
|
||||||
|
image = RLoadJXL(file);
|
||||||
|
break;
|
||||||
|
#endif /* USE_JXL */
|
||||||
|
|
||||||
#ifdef USE_GIF
|
#ifdef USE_GIF
|
||||||
case IM_GIF:
|
case IM_GIF:
|
||||||
image = RLoadGIF(file, index);
|
image = RLoadGIF(file, index);
|
||||||
@@ -305,6 +319,11 @@ char *RGetImageFileFormat(const char *file)
|
|||||||
return "JPEG";
|
return "JPEG";
|
||||||
#endif /* USE_JPEG */
|
#endif /* USE_JPEG */
|
||||||
|
|
||||||
|
#ifdef USE_JXL
|
||||||
|
case IM_JXL:
|
||||||
|
return "JXL";
|
||||||
|
#endif /* USE_JXL */
|
||||||
|
|
||||||
#ifdef USE_GIF
|
#ifdef USE_GIF
|
||||||
case IM_GIF:
|
case IM_GIF:
|
||||||
return "GIF";
|
return "GIF";
|
||||||
@@ -377,6 +396,13 @@ static WRImgFormat identFile(const char *path)
|
|||||||
if (buffer[0] == 0xff && buffer[1] == 0xd8)
|
if (buffer[0] == 0xff && buffer[1] == 0xd8)
|
||||||
return IM_JPEG;
|
return IM_JPEG;
|
||||||
|
|
||||||
|
/* check for JXL */
|
||||||
|
if ((buffer[0] == 0xff && buffer[1] == 0x0a) || /* naked codestream */
|
||||||
|
(buffer[0] == 0x00 && buffer[1] == 0x00 && buffer[2] == 0x00 && buffer[3] == 0x0c && /* container format */
|
||||||
|
buffer[4] == 0x4a && buffer[5] == 0x58 && buffer[6] == 0x4c && buffer[7] == 0x20 &&
|
||||||
|
buffer[8] == 0x0d && buffer[9] == 0x0a && buffer[10] == 0x87 && buffer[11] == 0x0a))
|
||||||
|
return IM_JXL;
|
||||||
|
|
||||||
/* check for GIF */
|
/* check for GIF */
|
||||||
if (buffer[0] == 'G' && buffer[1] == 'I' && buffer[2] == 'F' && buffer[3] == '8' &&
|
if (buffer[0] == 'G' && buffer[1] == 'I' && buffer[2] == 'F' && buffer[3] == '8' &&
|
||||||
(buffer[4] == '7' || buffer[4] == '9') && buffer[5] == 'a')
|
(buffer[4] == '7' || buffer[4] == '9') && buffer[5] == 'a')
|
||||||
|
|||||||
@@ -0,0 +1,211 @@
|
|||||||
|
/* load_jxl.c - load JXL (JPEG XL) image from file
|
||||||
|
*
|
||||||
|
* Raster graphics library
|
||||||
|
*
|
||||||
|
* Copyright (c) 2025 Window Maker Team
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library; if not, write to the Free
|
||||||
|
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
|
||||||
|
* MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
|
||||||
|
#ifdef USE_JXL
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#include <jxl/decode.h>
|
||||||
|
|
||||||
|
#include "wraster.h"
|
||||||
|
#include "imgformat.h"
|
||||||
|
#include "wr_i18n.h"
|
||||||
|
|
||||||
|
static unsigned char *do_read_file(const char *filename, size_t *size)
|
||||||
|
{
|
||||||
|
FILE *file;
|
||||||
|
struct stat st;
|
||||||
|
unsigned char *data;
|
||||||
|
|
||||||
|
if (stat(filename, &st) != 0) {
|
||||||
|
RErrorCode = RERR_OPEN;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
file = fopen(filename, "rb");
|
||||||
|
if (!file) {
|
||||||
|
RErrorCode = RERR_OPEN;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
*size = st.st_size;
|
||||||
|
data = malloc(*size);
|
||||||
|
if (!data) {
|
||||||
|
RErrorCode = RERR_NOMEMORY;
|
||||||
|
fclose(file);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fread(data, 1, *size, file) != *size) {
|
||||||
|
RErrorCode = RERR_READ;
|
||||||
|
free(data);
|
||||||
|
fclose(file);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(file);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
RImage *RLoadJXL(const char *file)
|
||||||
|
{
|
||||||
|
RImage *image = NULL;
|
||||||
|
unsigned char *data = NULL, *pixels = NULL;
|
||||||
|
size_t size;
|
||||||
|
JxlDecoder *dec = NULL;
|
||||||
|
JxlDecoderStatus status;
|
||||||
|
JxlBasicInfo info;
|
||||||
|
JxlPixelFormat format;
|
||||||
|
size_t buffer_size;
|
||||||
|
int width = 0, height = 0;
|
||||||
|
int has_alpha = 0;
|
||||||
|
|
||||||
|
/* Load file data */
|
||||||
|
data = do_read_file(file, &size);
|
||||||
|
if (!data)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* Create decoder */
|
||||||
|
dec = JxlDecoderCreate(NULL);
|
||||||
|
if (!dec) {
|
||||||
|
RErrorCode = RERR_NOMEMORY;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Subscribe to basic info and full image */
|
||||||
|
if (JxlDecoderSubscribeEvents(dec, JXL_DEC_BASIC_INFO | JXL_DEC_FULL_IMAGE) != JXL_DEC_SUCCESS) {
|
||||||
|
RErrorCode = RERR_BADIMAGEFILE;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set input data */
|
||||||
|
if (JxlDecoderSetInput(dec, data, size) != JXL_DEC_SUCCESS) {
|
||||||
|
RErrorCode = RERR_BADIMAGEFILE;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Process events */
|
||||||
|
for (;;) {
|
||||||
|
status = JxlDecoderProcessInput(dec);
|
||||||
|
|
||||||
|
if (status == JXL_DEC_ERROR) {
|
||||||
|
RErrorCode = RERR_BADIMAGEFILE;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status == JXL_DEC_NEED_MORE_INPUT) {
|
||||||
|
RErrorCode = RERR_BADIMAGEFILE;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status == JXL_DEC_BASIC_INFO) {
|
||||||
|
if (JxlDecoderGetBasicInfo(dec, &info) != JXL_DEC_SUCCESS) {
|
||||||
|
RErrorCode = RERR_BADIMAGEFILE;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
width = info.xsize;
|
||||||
|
height = info.ysize;
|
||||||
|
|
||||||
|
if (width < 1 || height < 1) {
|
||||||
|
RErrorCode = RERR_BADIMAGEFILE;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if image has alpha channel */
|
||||||
|
has_alpha = (info.alpha_bits > 0);
|
||||||
|
|
||||||
|
/* Set pixel format based on alpha channel presence */
|
||||||
|
if (has_alpha) {
|
||||||
|
format.num_channels = 4; /* RGBA */
|
||||||
|
} else {
|
||||||
|
format.num_channels = 3; /* RGB */
|
||||||
|
}
|
||||||
|
format.data_type = JXL_TYPE_UINT8;
|
||||||
|
format.endianness = JXL_NATIVE_ENDIAN;
|
||||||
|
format.align = 0;
|
||||||
|
|
||||||
|
} else if (status == JXL_DEC_NEED_IMAGE_OUT_BUFFER) {
|
||||||
|
/* Allocate image with or without alpha */
|
||||||
|
image = RCreateImage(width, height, has_alpha ? True : False);
|
||||||
|
if (!image) {
|
||||||
|
RErrorCode = RERR_NOMEMORY;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Determine buffer size */
|
||||||
|
if (JxlDecoderImageOutBufferSize(dec, &format, &buffer_size) != JXL_DEC_SUCCESS) {
|
||||||
|
RErrorCode = RERR_BADIMAGEFILE;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allocate buffer */
|
||||||
|
pixels = malloc(buffer_size);
|
||||||
|
if (!pixels) {
|
||||||
|
RErrorCode = RERR_NOMEMORY;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set output buffer */
|
||||||
|
if (JxlDecoderSetImageOutBuffer(dec, &format, pixels, buffer_size) != JXL_DEC_SUCCESS) {
|
||||||
|
RErrorCode = RERR_BADIMAGEFILE;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
} else if (status == JXL_DEC_FULL_IMAGE) {
|
||||||
|
/* Image is ready, copy data directly for RGB or RGBA */
|
||||||
|
if (has_alpha) {
|
||||||
|
/* RGBA format - copy directly */
|
||||||
|
memcpy(image->data, pixels, width * height * 4);
|
||||||
|
} else {
|
||||||
|
/* RGB format - copy directly */
|
||||||
|
memcpy(image->data, pixels, width * height * 3);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
} else if (status == JXL_DEC_SUCCESS) {
|
||||||
|
/* All done */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(data);
|
||||||
|
free(pixels);
|
||||||
|
JxlDecoderDestroy(dec);
|
||||||
|
return image;
|
||||||
|
|
||||||
|
error:
|
||||||
|
if (data)
|
||||||
|
free(data);
|
||||||
|
if (pixels)
|
||||||
|
free(pixels);
|
||||||
|
if (image)
|
||||||
|
RReleaseImage(image);
|
||||||
|
if (dec)
|
||||||
|
JxlDecoderDestroy(dec);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* USE_JXL */
|
||||||
@@ -29,6 +29,7 @@ POTFILES = \
|
|||||||
$(top_srcdir)/wrlib/load_ppm.c \
|
$(top_srcdir)/wrlib/load_ppm.c \
|
||||||
$(top_srcdir)/wrlib/load_gif.c \
|
$(top_srcdir)/wrlib/load_gif.c \
|
||||||
$(top_srcdir)/wrlib/load_jpeg.c \
|
$(top_srcdir)/wrlib/load_jpeg.c \
|
||||||
|
$(top_srcdir)/wrlib/load_jxl.c \
|
||||||
$(top_srcdir)/wrlib/load_png.c \
|
$(top_srcdir)/wrlib/load_png.c \
|
||||||
$(top_srcdir)/wrlib/load_tiff.c \
|
$(top_srcdir)/wrlib/load_tiff.c \
|
||||||
$(top_srcdir)/wrlib/load_xpm.c \
|
$(top_srcdir)/wrlib/load_xpm.c \
|
||||||
|
|||||||
+2
-2
@@ -3,7 +3,7 @@
|
|||||||
# 1998-2006 Dan Pascu
|
# 1998-2006 Dan Pascu
|
||||||
# 2013-2020 Window Maker Developers Team
|
# 2013-2020 Window Maker Developers Team
|
||||||
# This file is distributed under the same license as the Window Maker package.
|
# This file is distributed under the same license as the Window Maker package.
|
||||||
# Strahinya Radich (Страхиња Радић) <contact@strahinja.org>, 2023.
|
# Strahinya Radich (Страхиња Радић) <sr@strahinja.org>, 2023.
|
||||||
#
|
#
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -11,7 +11,7 @@ msgstr ""
|
|||||||
"Report-Msgid-Bugs-To: wmaker-dev@googlegroups.com\n"
|
"Report-Msgid-Bugs-To: wmaker-dev@googlegroups.com\n"
|
||||||
"POT-Creation-Date: 2023-11-02 19:43+0100\n"
|
"POT-Creation-Date: 2023-11-02 19:43+0100\n"
|
||||||
"PO-Revision-Date: 2023-11-02 19:48+0100\n"
|
"PO-Revision-Date: 2023-11-02 19:48+0100\n"
|
||||||
"Last-Translator: Страхиња Радић <contact@strahinja.org>\n"
|
"Last-Translator: Страхиња Радић <sr@strahinja.org>\n"
|
||||||
"Language-Team: Serbian <sr@li.org>\n"
|
"Language-Team: Serbian <sr@li.org>\n"
|
||||||
"Language: sr\n"
|
"Language: sr\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
|
|||||||
+20
-1
@@ -3,7 +3,7 @@
|
|||||||
* Raster graphics library
|
* Raster graphics library
|
||||||
*
|
*
|
||||||
* Copyright (c) 1998-2003 Alfredo K. Kojima
|
* Copyright (c) 1998-2003 Alfredo K. Kojima
|
||||||
* Copyright (c) 2013-2023 Window Maker Team
|
* Copyright (c) 2013-2025 Window Maker Team
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Library General Public
|
* modify it under the terms of the GNU Library General Public
|
||||||
@@ -40,6 +40,25 @@ Bool RSaveImage(RImage *image, const char *filename, const char *format)
|
|||||||
return RSaveTitledImage(image, filename, format, NULL);
|
return RSaveTitledImage(image, filename, format, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Bool RSaveRawImage(RImage *image, const char *format, unsigned char **out_buf, size_t *out_size)
|
||||||
|
{
|
||||||
|
#ifdef USE_PNG
|
||||||
|
if (strcasecmp(format, "PNG") == 0)
|
||||||
|
return RSaveRawPNG(image, NULL, out_buf, out_size);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_JPEG
|
||||||
|
if (strcasecmp(format, "JPG") == 0)
|
||||||
|
return RSaveRawJPEG(image, NULL, out_buf, out_size);
|
||||||
|
|
||||||
|
if (strcasecmp(format, "JPEG") == 0)
|
||||||
|
return RSaveRawJPEG(image, NULL, out_buf, out_size);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
RErrorCode = RERR_BADFORMAT;
|
||||||
|
return False;
|
||||||
|
}
|
||||||
|
|
||||||
Bool RSaveTitledImage(RImage *image, const char *filename, const char *format, char *title)
|
Bool RSaveTitledImage(RImage *image, const char *filename, const char *format, char *title)
|
||||||
{
|
{
|
||||||
#ifdef USE_PNG
|
#ifdef USE_PNG
|
||||||
|
|||||||
+120
-21
@@ -2,7 +2,7 @@
|
|||||||
*
|
*
|
||||||
* Raster graphics library
|
* Raster graphics library
|
||||||
*
|
*
|
||||||
* Copyright (c) 2023 Window Maker Team
|
* Copyright (c) 2023-2025 Window Maker Team
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Library General Public
|
* modify it under the terms of the GNU Library General Public
|
||||||
@@ -33,39 +33,92 @@
|
|||||||
#include "imgformat.h"
|
#include "imgformat.h"
|
||||||
#include "wr_i18n.h"
|
#include "wr_i18n.h"
|
||||||
|
|
||||||
|
/* Structure for JPEG memory destination */
|
||||||
|
struct jpeg_mem_data {
|
||||||
|
unsigned char **out_buf;
|
||||||
|
size_t *out_size;
|
||||||
|
unsigned char *buffer;
|
||||||
|
size_t buffer_size;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* JPEG memory destination methods */
|
||||||
|
static void jpeg_init_mem_destination(j_compress_ptr cinfo)
|
||||||
|
{
|
||||||
|
struct jpeg_mem_data *dest = (struct jpeg_mem_data *)cinfo->client_data;
|
||||||
|
dest->buffer_size = 32768; /* Initial buffer size */
|
||||||
|
dest->buffer = malloc(dest->buffer_size);
|
||||||
|
if (!dest->buffer) {
|
||||||
|
/* Memory allocation failed - will be caught by caller */
|
||||||
|
dest->buffer_size = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cinfo->dest->next_output_byte = dest->buffer;
|
||||||
|
cinfo->dest->free_in_buffer = dest->buffer_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean jpeg_empty_mem_output_buffer(j_compress_ptr cinfo)
|
||||||
|
{
|
||||||
|
struct jpeg_mem_data *dest = (struct jpeg_mem_data *)cinfo->client_data;
|
||||||
|
size_t old_size = dest->buffer_size;
|
||||||
|
dest->buffer_size *= 2;
|
||||||
|
dest->buffer = realloc(dest->buffer, dest->buffer_size);
|
||||||
|
if (!dest->buffer) {
|
||||||
|
/* Memory allocation failed - signal error */
|
||||||
|
dest->buffer_size = 0;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
cinfo->dest->next_output_byte = dest->buffer + old_size;
|
||||||
|
cinfo->dest->free_in_buffer = dest->buffer_size - old_size;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void jpeg_term_mem_destination(j_compress_ptr cinfo)
|
||||||
|
{
|
||||||
|
struct jpeg_mem_data *dest = (struct jpeg_mem_data *)cinfo->client_data;
|
||||||
|
*dest->out_size = dest->buffer_size - cinfo->dest->free_in_buffer;
|
||||||
|
*dest->out_buf = dest->buffer;
|
||||||
|
/* Don't free dest->buffer here - caller will free it */
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Save RImage to JPEG image
|
* Save RImage to JPEG data in memory
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Bool RSaveJPEG(RImage *img, const char *filename, char *title)
|
Bool RSaveRawJPEG(RImage *img, char *title, unsigned char **out_buf, size_t *out_size)
|
||||||
{
|
{
|
||||||
FILE *file;
|
int x, y;
|
||||||
int x, y, img_depth;
|
|
||||||
char *buffer;
|
char *buffer;
|
||||||
RColor pixel;
|
RColor pixel;
|
||||||
struct jpeg_compress_struct cinfo;
|
struct jpeg_compress_struct cinfo;
|
||||||
struct jpeg_error_mgr jerr;
|
struct jpeg_error_mgr jerr;
|
||||||
|
struct jpeg_destination_mgr jpeg_dest;
|
||||||
|
struct jpeg_mem_data mem_data;
|
||||||
JSAMPROW row_pointer;
|
JSAMPROW row_pointer;
|
||||||
|
|
||||||
file = fopen(filename, "wb");
|
*out_buf = NULL;
|
||||||
if (!file) {
|
*out_size = 0;
|
||||||
RErrorCode = RERR_OPEN;
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (img->format == RRGBAFormat)
|
|
||||||
img_depth = 4;
|
|
||||||
else
|
|
||||||
img_depth = 3;
|
|
||||||
|
|
||||||
/* collect separate RGB values to a buffer */
|
/* collect separate RGB values to a buffer */
|
||||||
buffer = malloc(sizeof(char) * 3 * img->width * img->height);
|
buffer = malloc(sizeof(char) * 3 * img->width * img->height);
|
||||||
|
if (!buffer) {
|
||||||
|
RErrorCode = RERR_NOMEMORY;
|
||||||
|
return False;
|
||||||
|
}
|
||||||
|
|
||||||
for (y = 0; y < img->height; y++) {
|
for (y = 0; y < img->height; y++) {
|
||||||
for (x = 0; x < img->width; x++) {
|
for (x = 0; x < img->width; x++) {
|
||||||
RGetPixel(img, x, y, &pixel);
|
RGetPixel(img, x, y, &pixel);
|
||||||
buffer[y*img->width*3+x*3+0] = (char)(pixel.red);
|
/* Handle transparent pixels by converting them to white
|
||||||
buffer[y*img->width*3+x*3+1] = (char)(pixel.green);
|
* since JPEG doesn't support transparency */
|
||||||
buffer[y*img->width*3+x*3+2] = (char)(pixel.blue);
|
if (pixel.alpha == 0) {
|
||||||
|
buffer[y*img->width*3+x*3+0] = (char)255; /* white red */
|
||||||
|
buffer[y*img->width*3+x*3+1] = (char)255; /* white green */
|
||||||
|
buffer[y*img->width*3+x*3+2] = (char)255; /* white blue */
|
||||||
|
} else {
|
||||||
|
buffer[y*img->width*3+x*3+0] = (char)(pixel.red);
|
||||||
|
buffer[y*img->width*3+x*3+1] = (char)(pixel.green);
|
||||||
|
buffer[y*img->width*3+x*3+2] = (char)(pixel.blue);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,7 +127,17 @@ Bool RSaveJPEG(RImage *img, const char *filename, char *title)
|
|||||||
|
|
||||||
/* Initialize cinfo structure */
|
/* Initialize cinfo structure */
|
||||||
jpeg_create_compress(&cinfo);
|
jpeg_create_compress(&cinfo);
|
||||||
jpeg_stdio_dest(&cinfo, file);
|
|
||||||
|
/* Set up custom memory destination */
|
||||||
|
mem_data.out_buf = out_buf;
|
||||||
|
mem_data.out_size = out_size;
|
||||||
|
jpeg_dest.init_destination = jpeg_init_mem_destination;
|
||||||
|
jpeg_dest.empty_output_buffer = jpeg_empty_mem_output_buffer;
|
||||||
|
jpeg_dest.term_destination = jpeg_term_mem_destination;
|
||||||
|
cinfo.dest = &jpeg_dest;
|
||||||
|
cinfo.dest->next_output_byte = NULL;
|
||||||
|
cinfo.dest->free_in_buffer = 0;
|
||||||
|
cinfo.client_data = &mem_data;
|
||||||
|
|
||||||
cinfo.image_width = img->width;
|
cinfo.image_width = img->width;
|
||||||
cinfo.image_height = img->height;
|
cinfo.image_height = img->height;
|
||||||
@@ -90,15 +153,51 @@ Bool RSaveJPEG(RImage *img, const char *filename, char *title)
|
|||||||
jpeg_write_marker(&cinfo, JPEG_COM, (const JOCTET*)title, strlen(title));
|
jpeg_write_marker(&cinfo, JPEG_COM, (const JOCTET*)title, strlen(title));
|
||||||
|
|
||||||
while (cinfo.next_scanline < cinfo.image_height) {
|
while (cinfo.next_scanline < cinfo.image_height) {
|
||||||
row_pointer = (JSAMPROW) &buffer[cinfo.next_scanline * img_depth * img->width];
|
row_pointer = (JSAMPROW) &buffer[cinfo.next_scanline * 3 * img->width];
|
||||||
jpeg_write_scanlines(&cinfo, &row_pointer, 1);
|
jpeg_write_scanlines(&cinfo, &row_pointer, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
jpeg_finish_compress(&cinfo);
|
jpeg_finish_compress(&cinfo);
|
||||||
|
jpeg_destroy_compress(&cinfo);
|
||||||
|
|
||||||
/* Clean */
|
/* Clean */
|
||||||
free(buffer);
|
free(buffer);
|
||||||
fclose(file);
|
|
||||||
|
return True;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Save RImage to JPEG file
|
||||||
|
*/
|
||||||
|
|
||||||
|
Bool RSaveJPEG(RImage *img, const char *filename, char *title)
|
||||||
|
{
|
||||||
|
FILE *file;
|
||||||
|
unsigned char *jpeg_data;
|
||||||
|
size_t jpeg_size;
|
||||||
|
size_t written;
|
||||||
|
|
||||||
|
/* Generate JPEG data in memory */
|
||||||
|
if (!RSaveRawJPEG(img, title, &jpeg_data, &jpeg_size)) {
|
||||||
|
return False;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write to file */
|
||||||
|
file = fopen(filename, "wb");
|
||||||
|
if (!file) {
|
||||||
|
free(jpeg_data);
|
||||||
|
RErrorCode = RERR_OPEN;
|
||||||
|
return False;
|
||||||
|
}
|
||||||
|
|
||||||
|
written = fwrite(jpeg_data, 1, jpeg_size, file);
|
||||||
|
fclose(file);
|
||||||
|
free(jpeg_data);
|
||||||
|
|
||||||
|
if (written != jpeg_size) {
|
||||||
|
RErrorCode = RERR_WRITE;
|
||||||
|
return False;
|
||||||
|
}
|
||||||
|
|
||||||
return True;
|
return True;
|
||||||
}
|
}
|
||||||
|
|||||||
+112
-18
@@ -2,7 +2,7 @@
|
|||||||
*
|
*
|
||||||
* Raster graphics library
|
* Raster graphics library
|
||||||
*
|
*
|
||||||
* Copyright (c) 2023 Window Maker Team
|
* Copyright (c) 2023-2025 Window Maker Team
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Library General Public
|
* modify it under the terms of the GNU Library General Public
|
||||||
@@ -33,12 +33,51 @@
|
|||||||
#include "imgformat.h"
|
#include "imgformat.h"
|
||||||
#include "wr_i18n.h"
|
#include "wr_i18n.h"
|
||||||
|
|
||||||
/*
|
/* Structure to hold PNG data in memory */
|
||||||
* Save RImage to PNG image
|
struct png_mem_data {
|
||||||
*/
|
unsigned char *buffer;
|
||||||
Bool RSavePNG(RImage *img, const char *filename, char *title)
|
size_t size;
|
||||||
|
size_t capacity;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Callback function to write PNG data to memory buffer */
|
||||||
|
static void png_write_to_memory(png_structp png_ptr, png_bytep data, png_size_t length)
|
||||||
|
{
|
||||||
|
struct png_mem_data *p = (struct png_mem_data *)png_get_io_ptr(png_ptr);
|
||||||
|
size_t new_size = p->size + length;
|
||||||
|
|
||||||
|
/* Expand buffer if necessary */
|
||||||
|
if (new_size > p->capacity) {
|
||||||
|
size_t new_capacity = p->capacity ? p->capacity * 2 : 8192;
|
||||||
|
while (new_capacity < new_size)
|
||||||
|
new_capacity *= 2;
|
||||||
|
|
||||||
|
unsigned char *new_buffer = realloc(p->buffer, new_capacity);
|
||||||
|
if (!new_buffer) {
|
||||||
|
png_error(png_ptr, "Out of memory");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
p->buffer = new_buffer;
|
||||||
|
p->capacity = new_capacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy data to buffer */
|
||||||
|
memcpy(p->buffer + p->size, data, length);
|
||||||
|
p->size += length;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Dummy flush function for memory I/O */
|
||||||
|
static void png_flush_memory(png_structp png_ptr)
|
||||||
|
{
|
||||||
|
/* No-op for memory I/O */
|
||||||
|
(void)png_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Save RImage to PNG data in memory
|
||||||
|
*/
|
||||||
|
Bool RSaveRawPNG(RImage *img, char *title, unsigned char **out_buf, size_t *out_size)
|
||||||
{
|
{
|
||||||
FILE *file;
|
|
||||||
png_structp png_ptr;
|
png_structp png_ptr;
|
||||||
png_infop png_info_ptr;
|
png_infop png_info_ptr;
|
||||||
png_bytep png_row;
|
png_bytep png_row;
|
||||||
@@ -46,17 +85,14 @@ Bool RSavePNG(RImage *img, const char *filename, char *title)
|
|||||||
int x, y;
|
int x, y;
|
||||||
int width = img->width;
|
int width = img->width;
|
||||||
int height = img->height;
|
int height = img->height;
|
||||||
|
struct png_mem_data png_data = {NULL, 0, 0};
|
||||||
|
|
||||||
file = fopen(filename, "wb");
|
*out_buf = NULL;
|
||||||
if (file == NULL) {
|
*out_size = 0;
|
||||||
RErrorCode = RERR_OPEN;
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Initialize write structure */
|
/* Initialize write structure */
|
||||||
png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
||||||
if (png_ptr == NULL) {
|
if (png_ptr == NULL) {
|
||||||
fclose(file);
|
|
||||||
RErrorCode = RERR_NOMEMORY;
|
RErrorCode = RERR_NOMEMORY;
|
||||||
return False;
|
return False;
|
||||||
}
|
}
|
||||||
@@ -64,19 +100,22 @@ Bool RSavePNG(RImage *img, const char *filename, char *title)
|
|||||||
/* Initialize info structure */
|
/* Initialize info structure */
|
||||||
png_info_ptr = png_create_info_struct(png_ptr);
|
png_info_ptr = png_create_info_struct(png_ptr);
|
||||||
if (png_info_ptr == NULL) {
|
if (png_info_ptr == NULL) {
|
||||||
fclose(file);
|
png_destroy_write_struct(&png_ptr, NULL);
|
||||||
RErrorCode = RERR_NOMEMORY;
|
RErrorCode = RERR_NOMEMORY;
|
||||||
return False;
|
return False;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Setup Exception handling */
|
/* Setup Exception handling */
|
||||||
if (setjmp(png_jmpbuf (png_ptr))) {
|
if (setjmp(png_jmpbuf(png_ptr))) {
|
||||||
fclose(file);
|
if (png_data.buffer)
|
||||||
|
free(png_data.buffer);
|
||||||
|
png_destroy_write_struct(&png_ptr, &png_info_ptr);
|
||||||
RErrorCode = RERR_INTERNAL;
|
RErrorCode = RERR_INTERNAL;
|
||||||
return False;
|
return False;
|
||||||
}
|
}
|
||||||
|
|
||||||
png_init_io(png_ptr, file);
|
/* Set up memory I/O */
|
||||||
|
png_set_write_fn(png_ptr, &png_data, png_write_to_memory, png_flush_memory);
|
||||||
|
|
||||||
/* Write header (8 bit colour depth) */
|
/* Write header (8 bit colour depth) */
|
||||||
png_set_IHDR(png_ptr, png_info_ptr, width, height, 8, PNG_COLOR_TYPE_RGB,
|
png_set_IHDR(png_ptr, png_info_ptr, width, height, 8, PNG_COLOR_TYPE_RGB,
|
||||||
@@ -96,6 +135,13 @@ Bool RSavePNG(RImage *img, const char *filename, char *title)
|
|||||||
|
|
||||||
/* Allocate memory for one row (3 bytes per pixel - RGB) */
|
/* Allocate memory for one row (3 bytes per pixel - RGB) */
|
||||||
png_row = (png_bytep) malloc(3 * width * sizeof(png_byte));
|
png_row = (png_bytep) malloc(3 * width * sizeof(png_byte));
|
||||||
|
if (!png_row) {
|
||||||
|
if (png_data.buffer)
|
||||||
|
free(png_data.buffer);
|
||||||
|
png_destroy_write_struct(&png_ptr, &png_info_ptr);
|
||||||
|
RErrorCode = RERR_NOMEMORY;
|
||||||
|
return False;
|
||||||
|
}
|
||||||
|
|
||||||
/* Write image data */
|
/* Write image data */
|
||||||
for (y = 0; y < height; y++) {
|
for (y = 0; y < height; y++) {
|
||||||
@@ -114,8 +160,7 @@ Bool RSavePNG(RImage *img, const char *filename, char *title)
|
|||||||
/* End write */
|
/* End write */
|
||||||
png_write_end(png_ptr, NULL);
|
png_write_end(png_ptr, NULL);
|
||||||
|
|
||||||
/* Clean */
|
/* Clean up structures */
|
||||||
fclose(file);
|
|
||||||
if (png_info_ptr != NULL)
|
if (png_info_ptr != NULL)
|
||||||
png_free_data(png_ptr, png_info_ptr, PNG_FREE_ALL, -1);
|
png_free_data(png_ptr, png_info_ptr, PNG_FREE_ALL, -1);
|
||||||
if (png_ptr != NULL)
|
if (png_ptr != NULL)
|
||||||
@@ -123,5 +168,54 @@ Bool RSavePNG(RImage *img, const char *filename, char *title)
|
|||||||
if (png_row != NULL)
|
if (png_row != NULL)
|
||||||
free(png_row);
|
free(png_row);
|
||||||
|
|
||||||
|
/* Return the buffer */
|
||||||
|
*out_buf = png_data.buffer;
|
||||||
|
*out_size = png_data.size;
|
||||||
|
|
||||||
|
return True;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Save RImage to PNG image
|
||||||
|
*/
|
||||||
|
Bool RSavePNG(RImage *img, const char *filename, char *title)
|
||||||
|
{
|
||||||
|
FILE *file;
|
||||||
|
unsigned char *png_data = NULL;
|
||||||
|
size_t png_size = 0;
|
||||||
|
size_t written;
|
||||||
|
|
||||||
|
if (!img || !filename) {
|
||||||
|
RErrorCode = RERR_BADIMAGEFILE;
|
||||||
|
return False;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Use RSaveRawPNG to generate PNG data in memory */
|
||||||
|
if (!RSaveRawPNG(img, title, &png_data, &png_size)) {
|
||||||
|
/* Error code already set by RSaveRawPNG */
|
||||||
|
return False;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Open file for writing */
|
||||||
|
file = fopen(filename, "wb");
|
||||||
|
if (file == NULL) {
|
||||||
|
free(png_data);
|
||||||
|
RErrorCode = RERR_OPEN;
|
||||||
|
return False;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write PNG data to file */
|
||||||
|
written = fwrite(png_data, 1, png_size, file);
|
||||||
|
fclose(file);
|
||||||
|
|
||||||
|
/* Check if all data was written */
|
||||||
|
if (written != png_size) {
|
||||||
|
free(png_data);
|
||||||
|
RErrorCode = RERR_WRITE;
|
||||||
|
return False;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clean up */
|
||||||
|
free(png_data);
|
||||||
return True;
|
return True;
|
||||||
}
|
}
|
||||||
|
|||||||
+24
-3
@@ -244,8 +244,25 @@ static double Mitchell_filter(double t)
|
|||||||
return (0.0);
|
return (0.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static double (*filterf)(double) = Mitchell_filter;
|
#define CatmullRom_support (2.0)
|
||||||
static double fwidth = Mitchell_support;
|
|
||||||
|
static double CatmullRom_filter(double t)
|
||||||
|
{
|
||||||
|
double tt;
|
||||||
|
|
||||||
|
tt = t * t;
|
||||||
|
if (t < 0)
|
||||||
|
t = -t;
|
||||||
|
if (t < 1.0) {
|
||||||
|
return ((1.5 * t * tt) - (2.5 * tt) + 1.0);
|
||||||
|
} else if (t < 2.0) {
|
||||||
|
return ((-0.5 * t * tt) + (2.5 * tt) - (4.0 * t) + 2.0);
|
||||||
|
}
|
||||||
|
return (0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static double (*filterf)(double) = CatmullRom_filter;
|
||||||
|
static double fwidth = CatmullRom_support;
|
||||||
|
|
||||||
void wraster_change_filter(RScalingFilter type)
|
void wraster_change_filter(RScalingFilter type)
|
||||||
{
|
{
|
||||||
@@ -270,11 +287,15 @@ void wraster_change_filter(RScalingFilter type)
|
|||||||
filterf = Lanczos3_filter;
|
filterf = Lanczos3_filter;
|
||||||
fwidth = Lanczos3_support;
|
fwidth = Lanczos3_support;
|
||||||
break;
|
break;
|
||||||
default:
|
|
||||||
case RMitchellFilter:
|
case RMitchellFilter:
|
||||||
filterf = Mitchell_filter;
|
filterf = Mitchell_filter;
|
||||||
fwidth = Mitchell_support;
|
fwidth = Mitchell_support;
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
case RCatmullRomFilter:
|
||||||
|
filterf = CatmullRom_filter;
|
||||||
|
fwidth = CatmullRom_support;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+5
-1
@@ -143,7 +143,8 @@ typedef enum {
|
|||||||
RBellFilter,
|
RBellFilter,
|
||||||
RBSplineFilter,
|
RBSplineFilter,
|
||||||
RLanczos3Filter,
|
RLanczos3Filter,
|
||||||
RMitchellFilter
|
RMitchellFilter,
|
||||||
|
RCatmullRomFilter
|
||||||
} RScalingFilter;
|
} RScalingFilter;
|
||||||
|
|
||||||
|
|
||||||
@@ -391,6 +392,9 @@ RImage *RGetImageFromXPMData(RContext *context, char **xpmData)
|
|||||||
Bool RSaveImage(RImage *image, const char *filename, const char *format)
|
Bool RSaveImage(RImage *image, const char *filename, const char *format)
|
||||||
__wrlib_nonnull(1, 2, 3);
|
__wrlib_nonnull(1, 2, 3);
|
||||||
|
|
||||||
|
Bool RSaveRawImage(RImage *image, const char *format, unsigned char **out_buf, size_t *out_size)
|
||||||
|
__wrlib_nonnull(1, 2, 3, 4);
|
||||||
|
|
||||||
Bool RSaveTitledImage(RImage *image, const char *filename, const char *format, char *title)
|
Bool RSaveTitledImage(RImage *image, const char *filename, const char *format, char *title)
|
||||||
__wrlib_nonnull(1, 2, 3);
|
__wrlib_nonnull(1, 2, 3);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user