1
0
mirror of https://github.com/gryf/wmaker.git synced 2026-04-28 19:44:06 +02:00

Compare commits

...

6 Commits

Author SHA1 Message Date
David Maciejak 5b631cad93 wmaker: fix EmulateAppIcon index from advanced_option
This patch is fixing the EmulateAppIcon index which should be
moreChk[8], moreChk[7] used until now is for DontSaveSession
attribute.
2026-04-06 23:47:47 +01:00
David Maciejak ee9fd77a56 wmaker: fix crash for windows without WM_HINTS
This patch is adding a guard before calling wm_hints->icon_pixmap.
Crash can be reproduced with decoration-less apps when disabling
"Emulate application icon" attribute.

Ref:

Program terminated with signal SIGSEGV, Segmentation fault.
806 if (!getSize(wwin->wm_hints->icon_pixmap, &w, &h, &d)) {
[Current thread is 1 (Thread 0x7ffff660ed40 (LWP 29297))]
2026-04-06 23:47:47 +01:00
David Maciejak 62e341b5cc wmaker: add test for _NET_WM_FULLSCREEN_MONITORS
This patch is adding a small test app to validate that
_NET_WM_FULLSCREEN_MONITORS is working as expected.
2026-04-05 21:47:05 +01:00
David Maciejak fa49b7c003 WINGs: avoid splitting UTF-8 characters when wrapping text
This patch is to split UTF-8 word by characters and not bytes.
Issue reported at https://github.com/window-maker/wmaker/issues/65
2026-04-04 21:35:36 +01:00
David Maciejak 6dbc6c95ab WINGs: make UTF-8 functions global
This patch is moving the existing UTF-8 functions from wtextfield.c
to WINGsP.h.in to be available to all modules.
2026-04-04 21:35:36 +01:00
David Maciejak 4babc0e422 Doc: fix typos in NEWS and README 2026-04-04 15:41:07 +01:00
9 changed files with 217 additions and 67 deletions
+25 -25
View File
@@ -276,12 +276,12 @@ file.
Alternative way for traverse half-maximized windows
---------------------------------------------------
For now, there could be three possible state of the window while using
half-maximized feature. Unmaximized window have its state saved during that
process, which was use to unmaximize it. For example, if there is a window,
which is maximized on the half left side of the screen, and while requesting
left-half-maximized, it become unmaximized with size and dimension restored to
original state.
For now, there could be three possible states of the window while using
the half-maximized feature. Unmaximized windows have their state saved during
that process, which is used to unmaximize them. For example, if there is a
window that is maximized on the left half of the screen, and while requesting
left-half-maximize it becomes unmaximized with its size and dimensions
restored to the original state.
By setting "AlternativeHalfMaximized" option to "Yes"
~/GNUstep/Defaults/WindowMaker config file (or by using WPrefs.app and option
@@ -309,9 +309,9 @@ Window can be moved using keyboard shortcut right-half-maximize:
├┬┐ └──────────┘│
└┴┴────────────────────┘
Further invoking right-half-maximize will do nothing. Note, that window always
can be unmaximzied using appropriate keyboard shortcut or by selecting
"Unmaximize" from window menu.
Further invoking right-half-maximize will do nothing. Note, that the window always
can be unmaximized using an appropriate keyboard shortcut or by selecting
"Unmaximize" from the window menu.
Going to opposite direction by invoking left-half-maximize, will make the window
maximized in both, vertical and horizontal directions:
@@ -402,8 +402,8 @@ left and second display is on the right with window on first screen:
├┬┐ ├┬┬┐ │
└┴┴───────────────┴┴┴┴───────────────┘
It can be right-half-maximized (using previously defined key combination), so it
become:
It can be right-half-maximized (using the previously defined key combination), so it
becomes:
┌┬───────┬────────┬─────────────────┬┐
├┘ ├────────┤ ├┤
@@ -415,7 +415,7 @@ become:
└┴┴───────────────┴┴┴┴───────────────┘
In this example there is an assumption that WindowMaker is configured, that
maximized windows wont cover mini icons nor dock.
maximized windows won't cover mini icons nor the dock.
Without setting new option to true, issuing another right-half-maximize will
restore window dimensions and position to the original state (like on the first
@@ -430,7 +430,7 @@ figure). With new option set to true it will move window to second screen like:
├┬┐ ├┬┬┬─────┘ │
└┴┴───────────────┴┴┴┴───────────────┘
Another activation of right-half-maxmimize:
Another activation of right-half-maximize:
┌┬────────────────┬────────┬────────┬┐
├┘ │ ├────────┼┤
@@ -441,7 +441,7 @@ Another activation of right-half-maxmimize:
├┬┐ ├┬┬┐ └────────┘│
└┴┴───────────────┴┴┴┴───────────────┘
And final activation of right-half-maxmimize:
And final activation of right-half-maximize:
┌┬────────────────┬───────┬─────────┬┐
├┘ ├───────┤ ├┤
@@ -452,8 +452,8 @@ And final activation of right-half-maxmimize:
├┬┐ ├┬┬┐ │
└┴┴───────────────┴┴┴┴───────────────┘
Where window is restored its size (but not position, since it it on different
head now). Moving window in directions like left-half-maximize,
Where the window is restored to its size (but not position, since it is on a different
head now). Moving a window in directions like left-half-maximize,
top-half-maximize and bottom-half-maximize will behave in similar way depending
on the layout of displays.
@@ -525,12 +525,12 @@ There are four choices:
geometry is restored.
* "Unmaximize" ("...consider the window unmaximized") causes a maximized window
to be moved when dragged and remains partially maximized, i.e., it keeps its
maximized geometry, but is consider to be unmaximized. In particular, it can
maximized geometry, but is considered to be unmaximized. In particular, it can
be immediately re-maximized.
* "NoMove" ("...do not move the window") prevents a maximized window from being
moved when dragged.
Note that, to accomodate this option in the "Window Handling Preferences" tab in
Note that, to accommodate this option in the "Window Handling Preferences" tab in
WPrefs.app, the option to "Open dialogs in the same workspace as their owners"
(which sets the "OpenTransientOnOwnerWorkspace" option from
~/GNUstep/Defaults/WindowMaker) has been moved to "Expert User Preferences".
@@ -1330,7 +1330,7 @@ Others
- added DONT_SCALE_ICONS compile time option
- added --dont-restore cmd line option. When passed to wmaker, it
wont restore the state saved previously.
won't restore the state saved previously.
--- 0.61.1
@@ -1870,10 +1870,10 @@ Clip icons when the mouse pointer enter/leave the Clip. To avoid unwanted
raising/lowering there is a time threshold before raising/lowering.
The thresholds can be changed in wconfig.h by changing one or both of
AUTO_LOWER_DELAY and AUTO_RAISE_DELAY (expressed in milliseconds).
For example if you set AUTO_RAISE_DELAY to 0, then the Clip will be raised as
For example, if you set AUTO_RAISE_DELAY to 0, then the Clip will be raised as
soon as the mouse pointer enters its area. Setting AUTO_RAISE_DELAY to a very
big value, will make the Clip to practically do not auto raise unless clicked,
but to be automatically lowered after AUTO_LOWER_DELAY (ms) when leaved.
big value will make the Clip practically not auto-raise unless clicked,
but it will still be automatically lowered after AUTO_LOWER_DELAY (ms) when left.
New ThemePack Format
@@ -2640,7 +2640,7 @@ applets of that kind, because the icon window do not belongs to WindowMaker,
but to the application itself. For such icons you must keep the mouse over the
icon groundplate, else it will collapse back. But usually these type of icons
will not stay in a collapsed clip, since one needs to see what they show.
When the clip is leaved it will collapse back after a delay of 1 second, unless
When the clip is left it will collapse back after a delay of 1 second, unless
the mouse is moved back to the clip area. The delay can be set modifying
AUTO_COLLAPSE_DELAY in wconfig.h. Default is 1000 (ms) which means 1 second.
@@ -2977,8 +2977,8 @@ When the step to move becomes smaller than IconSlideStep, IconSlideStep will
be used further until the destination is reached.
This way a nice deceleration effect is achieved, since while the icon
approaches destination, it will use smaller steps, gibing the illusion that
the icons is moving slower.
approaches the destination, it will use smaller steps, giving the illusion that
the icons are moving slower.
IconSlideDelay will give the pause between steps, and is expressed in ms.
+5 -5
View File
@@ -190,7 +190,7 @@ Performance Tuning
==================
If you want to diminish Window Maker's memory usage and improve performance,
while keeping a nice appearance and good functionality, follow the items bellow:
while keeping a nice appearance and good functionality, follow the items below:
- use solid textures for everything, mainly title bars and menus. If you want a
nice looking desktop, use the Traditional style.
@@ -240,7 +240,7 @@ pointer faster;
clicked with the 0 (Ins) key.
The above key values work in a XFree86 3.2 (X11R6.1) X server but your
The above key values work on an XFree86 3.2 (X11R6.1) X server, but your
mileage may vary.
@@ -252,7 +252,7 @@ that crashes Window Maker, please send a backtrace with your bug report.
To make a useful backtrace, you need a core file with debugging information
produced by Window Maker when it crashes. It should have been installed without
stripping too.
being stripped.
To compile wmaker with debugging information:
@@ -287,7 +287,7 @@ The icons listed in COPYING.WTFPL and are distributed in this program and were
made by Banlu Kemiyatorn (]d), are licensed through the "do What The Fuck you
want to Public License". Read the COPYING.WTFPL file for the complete license.
NeXT, OpenStep and NEXTSTEP are a trademarks of NeXT Computer, Inc. All other
NeXT, OpenStep and NEXTSTEP are trademarks of NeXT Computer, Inc. All other
trademarks are property of their respective owners.
The authors reserve the right to make changes in the software without prior
@@ -307,7 +307,7 @@ screenshots.
The AUTHORS file contains a list of the people who have contributed to the
project. The name of people who have helped with localization (translation) can
project. The names of people who have helped with localization (translation) can
be found in po/README and Window Maker/README
If you have any comments, fixes and bug reports (filled BUGFORMs) send them
+31
View File
@@ -686,6 +686,37 @@ void W_BroadcastMessage(W_View *targetParent, XEvent *event);
void W_DispatchMessage(W_View *target, XEvent *event);
/* ---[ UTF-8 helpers ]--------------------------------------------------- */
static inline int oneUTF8CharBackward(const char *str, int len)
{
const unsigned char *ustr = (const unsigned char *)str;
int pos = 0;
while (len-- > 0 && ustr[--pos] >= 0x80 && ustr[pos] <= 0xbf) ;
return pos;
}
static inline int oneUTF8CharForward(const char *str, int len)
{
const unsigned char *ustr = (const unsigned char *)str;
int pos = 0;
while (len-- > 0 && ustr[++pos] >= 0x80 && ustr[pos] <= 0xbf) ;
return pos;
}
// find the beginning of the UTF8 char pointed by str
static inline int seekUTF8CharStart(const char *str, int len)
{
const unsigned char *ustr = (const unsigned char *)str;
int pos = 0;
while (len-- > 0 && ustr[pos] >= 0x80 && ustr[pos] <= 0xbf)
--pos;
return pos;
}
#ifdef __cplusplus
}
+7 -4
View File
@@ -122,11 +122,14 @@ static int fitText(const char *text, WMFont * font, int width, int wrap)
word1 = word2;
}
for (i = word1; i < word2; i++) {
w = WMWidthOfString(font, text, i);
if (w > width) {
/* Advance character by character (not byte by byte) */
i = word1;
while (i < word2) {
int next_i = i + oneUTF8CharForward(text + i, word2 - i);
w = WMWidthOfString(font, text, next_i);
if (w > width)
break;
}
i = next_i;
}
/* keep words complete if possible */
-29
View File
@@ -122,35 +122,6 @@ static WMSelectionProcs selectionHandler = {
#define TEXT_WIDTH2(tPtr, start, end) (WMWidthOfString((tPtr)->font, \
&((tPtr)->text[(start)]), (end) - (start)))
static inline int oneUTF8CharBackward(const char *str, int len)
{
const unsigned char *ustr = (const unsigned char *)str;
int pos = 0;
while (len-- > 0 && ustr[--pos] >= 0x80 && ustr[pos] <= 0xbf) ;
return pos;
}
static inline int oneUTF8CharForward(const char *str, int len)
{
const unsigned char *ustr = (const unsigned char *)str;
int pos = 0;
while (len-- > 0 && ustr[++pos] >= 0x80 && ustr[pos] <= 0xbf) ;
return pos;
}
// find the beginning of the UTF8 char pointed by str
static inline int seekUTF8CharStart(const char *str, int len)
{
const unsigned char *ustr = (const unsigned char *)str;
int pos = 0;
while (len-- > 0 && ustr[pos] >= 0x80 && ustr[pos] <= 0xbf)
--pos;
return pos;
}
static void normalizeRange(TextField * tPtr, WMRange * range)
{
if (range->position < 0 && range->count < 0)
+3
View File
@@ -803,6 +803,9 @@ RImage *get_rimage_icon_from_wm_hints(WIcon *icon)
wwin = icon->owner;
if (!wwin->wm_hints)
return NULL;
if (!getSize(wwin->wm_hints->icon_pixmap, &w, &h, &d)) {
icon->owner->wm_hints->flags &= ~IconPixmapHint;
return NULL;
+3 -3
View File
@@ -1443,10 +1443,10 @@ static void create_tab_app_specific(WWindow *wwin, InspectorPanel *panel, int fr
if (WFLAGP(wwin, emulate_appicon)) {
WMSetButtonEnabled(panel->appChk[1], False);
WMSetButtonEnabled(panel->moreChk[7], True);
WMSetButtonEnabled(panel->moreChk[8], True);
} else {
WMSetButtonEnabled(panel->appChk[1], True);
WMSetButtonEnabled(panel->moreChk[7], False);
WMSetButtonEnabled(panel->moreChk[8], False);
}
} else {
if ((wwin->transient_for != None && wwin->transient_for != scr->root_win)
@@ -1455,7 +1455,7 @@ static void create_tab_app_specific(WWindow *wwin, InspectorPanel *panel, int fr
else
tmp = True;
WMSetButtonEnabled(panel->moreChk[7], tmp);
WMSetButtonEnabled(panel->moreChk[8], tmp);
WMSetPopUpButtonItemEnabled(panel->pagePopUp, 4, False);
panel->appFrm = NULL;
+7 -1
View File
@@ -4,10 +4,16 @@ AUTOMAKE_OPTIONS = no-dependencies
EXTRA_DIST = notest.c
noinst_PROGRAMS = wtest
noinst_PROGRAMS = wtest wm_fsm_test
wtest_SOURCES = wtest.c
wtest_LDADD = $(top_builddir)/wmlib/libWMaker.la @XLFLAGS@ @XLIBS@
AM_CPPFLAGS = -g -D_BSD_SOURCE @XCFLAGS@ -I$(top_srcdir)/wmlib
wm_fsm_test_SOURCES = wm_fsm_test.c
wm_fsm_test_CPPFLAGS = $(shell pkg-config --cflags gtk+-3.0)
wm_fsm_test_LDFLAGS = $(shell pkg-config --libs gtk+-3.0) -lX11
+136
View File
@@ -0,0 +1,136 @@
/* test application that demonstrates _NET_WM_FULLSCREEN_MONITORS
*
* how to run it:
* G_MESSAGES_DEBUG=all ./wm_fsm_test
*/
#include <gtk/gtk.h>
#include <gdk/gdkx.h>
#include <string.h>
static GtkWidget* window;
static gboolean print_final_size(gpointer data)
{
(void)data;
gint w, h;
gtk_window_get_size(GTK_WINDOW(window), &w, &h);
g_debug("final window size: %dx%d", w, h);
return FALSE;
}
static gboolean on_configure_after_unfullscreen(GtkWidget *widget, GdkEventConfigure *event, gpointer data)
{
(void)event;
(void)data;
g_signal_handlers_disconnect_by_func(widget, on_configure_after_unfullscreen, data);
g_idle_add(print_final_size, NULL);
return FALSE;
}
static gboolean fullscreen(gpointer data)
{
(void)data;
g_debug("fullscreen()");
gtk_window_fullscreen(GTK_WINDOW(window));
return FALSE;
}
static gboolean on_window_state_event(GtkWidget *widget, GdkEventWindowState *event, gpointer data)
{
(void)widget;
(void)data;
if ((event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) &&
!(event->new_window_state & GDK_WINDOW_STATE_FULLSCREEN)) {
/* Force geometry back */
gtk_window_move(GTK_WINDOW(window), 0, 0);
gtk_window_resize(GTK_WINDOW(window), 800, 600);
g_signal_connect(window, "configure-event", G_CALLBACK(on_configure_after_unfullscreen), NULL);
}
return FALSE;
}
static gboolean unfullscreen(gpointer data)
{
(void)data;
g_debug("unfullscreen()");
gtk_window_unfullscreen(GTK_WINDOW(window));
return FALSE;
}
static gboolean switch_monitors(gpointer data)
{
static const long monitors[4][4] = {
{0, 0, 0, 1},
{0, 0, 0, 0},
{1, 1, 1, 1},
{0, 0, 0, 1}
};
static const char* desc[4] = {
"Window should be covering both heads 1 and 2\n",
"Window should be covering just the first head\n",
"Window should be covering just the second head\n",
"Window should be covering both heads 1 and 2\n"
};
guint index = GPOINTER_TO_UINT(data);
g_debug("%s", desc[index]);
GdkDisplay *display = gdk_display_get_default();
GdkWindow *gwin = gtk_widget_get_window(window);
if (!gwin) {
g_warning("switch_monitors: window not realized yet");
return FALSE;
}
XClientMessageEvent xclient;
memset(&xclient, 0, sizeof(xclient));
xclient.type = ClientMessage;
xclient.window = GDK_WINDOW_XID(gwin);
xclient.message_type = gdk_x11_get_xatom_by_name_for_display(display, "_NET_WM_FULLSCREEN_MONITORS");
xclient.format = 32;
xclient.data.l[0] = monitors[index][0];
xclient.data.l[1] = monitors[index][1];
xclient.data.l[2] = monitors[index][2];
xclient.data.l[3] = monitors[index][3];
xclient.data.l[4] = 1;
XSendEvent(GDK_WINDOW_XDISPLAY(gwin),
GDK_WINDOW_XID(gdk_get_default_root_window()),
False,
SubstructureRedirectMask | SubstructureNotifyMask,
(XEvent *) &xclient);
return FALSE;
}
static gboolean quit(gpointer data)
{
(void)data;
gtk_main_quit();
return FALSE;
}
int main(int argc, char** argv)
{
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_default_size(GTK_WINDOW(window), 800, 600);
gtk_widget_show(window);
g_signal_connect(window, "window-state-event", G_CALLBACK(on_window_state_event), NULL);
g_timeout_add(1000, (GSourceFunc) fullscreen, NULL);
g_timeout_add(5000, (GSourceFunc) switch_monitors, GUINT_TO_POINTER(0));
g_timeout_add(10000, (GSourceFunc) switch_monitors, GUINT_TO_POINTER(1));
g_timeout_add(15000, (GSourceFunc) switch_monitors, GUINT_TO_POINTER(2));
g_timeout_add(20000, (GSourceFunc) switch_monitors, GUINT_TO_POINTER(3));
g_timeout_add(25000, (GSourceFunc) unfullscreen, NULL);
g_timeout_add(30000, (GSourceFunc) quit, NULL);
gtk_main();
}